1#[macro_use]
10extern crate tracing;
11
12pub mod add_services;
13pub mod cmd;
14pub mod config;
15pub mod error;
16pub mod helpers;
17pub mod local;
18pub mod rpc;
19pub mod rpc_client;
20
21pub const DEFAULT_NODE_STARTUP_CONNECTION_TIMEOUT_S: u64 = 300;
22
23#[derive(Clone, Copy, PartialEq, Debug)]
24pub enum VerbosityLevel {
25 Minimal,
26 Normal,
27 Full,
28}
29
30impl From<u8> for VerbosityLevel {
31 fn from(verbosity: u8) -> Self {
32 match verbosity {
33 1 => VerbosityLevel::Minimal,
34 2 => VerbosityLevel::Normal,
35 3 => VerbosityLevel::Full,
36 _ => VerbosityLevel::Normal,
37 }
38 }
39}
40
41use crate::error::{Error, Result};
42use ant_service_management::NodeRegistryManager;
43use ant_service_management::rpc::RpcActions;
44use ant_service_management::{
45 NodeService, ServiceStateActions, ServiceStatus, UpgradeOptions, UpgradeResult,
46 control::ServiceControl, error::Error as ServiceError, rpc::RpcClient,
47};
48use colored::Colorize;
49use indicatif::ProgressBar;
50use indicatif::ProgressStyle;
51use semver::Version;
52use std::sync::Arc;
53use tracing::debug;
54
55pub const DAEMON_DEFAULT_PORT: u16 = 12500;
56pub const DAEMON_SERVICE_NAME: &str = "antctld";
57
58const RPC_START_UP_DELAY_MS: u64 = 3000;
59
60pub struct ServiceManager<T: ServiceStateActions + Send> {
61 pub service: T,
62 pub service_control: Box<dyn ServiceControl + Send>,
63 pub verbosity: VerbosityLevel,
64}
65
66impl<T: ServiceStateActions + Send> ServiceManager<T> {
67 pub fn new(
68 service: T,
69 service_control: Box<dyn ServiceControl + Send>,
70 verbosity: VerbosityLevel,
71 ) -> Self {
72 ServiceManager {
73 service,
74 service_control,
75 verbosity,
76 }
77 }
78
79 pub async fn start(&mut self) -> Result<()> {
80 let service_name = self.service.name().await;
81 info!("Starting the {service_name} service");
82 if ServiceStatus::Running == self.service.status().await {
83 if self
89 .service_control
90 .get_process_pid(&self.service.bin_path().await)
91 .is_ok()
92 {
93 debug!("The {service_name} service is already running",);
94 if self.verbosity != VerbosityLevel::Minimal {
95 println!("The {service_name} service is already running",);
96 }
97 return Ok(());
98 }
99 }
100
101 if self.verbosity != VerbosityLevel::Minimal {
104 println!("Attempting to start {service_name}...");
105 }
106 self.service_control
107 .start(&service_name, self.service.is_user_mode().await)?;
108 self.service_control.wait(RPC_START_UP_DELAY_MS);
109
110 match self
116 .service_control
117 .get_process_pid(&self.service.bin_path().await)
118 {
119 Ok(pid) => {
120 debug!(
121 "Service process started for {service_name} with PID {}",
122 pid
123 );
124 self.service.on_start(Some(pid), true).await?;
125
126 info!("Service {service_name} has been started successfully");
127 }
128 Err(ant_service_management::error::Error::ServiceProcessNotFound(_)) => {
129 error!(
130 "The '{service_name}' service has failed to start because ServiceProcessNotFound when fetching PID"
131 );
132 return Err(Error::PidNotFoundAfterStarting);
133 }
134 Err(err) => {
135 error!("Failed to start service, because PID could not be obtained: {err}");
136 return Err(err.into());
137 }
138 };
139
140 if self.verbosity != VerbosityLevel::Minimal {
141 println!("{} Started {service_name} service", "✓".green(),);
142 println!(
143 " - PID: {}",
144 self.service
145 .pid()
146 .await
147 .map_or("-".to_string(), |p| p.to_string())
148 );
149 println!(
150 " - Bin path: {}",
151 self.service.bin_path().await.to_string_lossy()
152 );
153 println!(
154 " - Data path: {}",
155 self.service.data_dir_path().await.to_string_lossy()
156 );
157 println!(
158 " - Logs path: {}",
159 self.service.log_dir_path().await.to_string_lossy()
160 );
161 }
162 Ok(())
163 }
164
165 pub async fn stop(&mut self) -> Result<()> {
166 let service_name = self.service.name().await;
167 info!("Stopping the {service_name} service");
168 match self.service.status().await {
169 ServiceStatus::Added => {
170 debug!("The {service_name} service has not been started since it was installed",);
171 if self.verbosity != VerbosityLevel::Minimal {
172 println!("Service {service_name} has not been started since it was installed",);
173 }
174 Ok(())
175 }
176 ServiceStatus::Removed => {
177 debug!("The {service_name} service has been removed");
178 if self.verbosity != VerbosityLevel::Minimal {
179 println!("Service {service_name} has been removed");
180 }
181 Ok(())
182 }
183 ServiceStatus::Running => {
184 let pid = self.service.pid().await.ok_or(Error::PidNotSet)?;
185
186 if self
187 .service_control
188 .get_process_pid(&self.service.bin_path().await)
189 .is_ok()
190 {
191 if self.verbosity != VerbosityLevel::Minimal {
192 println!("Attempting to stop {service_name}...");
193 }
194 self.service_control
195 .stop(&service_name, self.service.is_user_mode().await)?;
196 if self.verbosity != VerbosityLevel::Minimal {
197 println!(
198 "{} Service {service_name} with PID {} was stopped",
199 "✓".green(),
200 pid
201 );
202 }
203 } else if self.verbosity != VerbosityLevel::Minimal {
204 debug!("Service {service_name} was already stopped");
205 println!("{} Service {service_name} was already stopped", "✓".green());
206 }
207
208 self.service.on_stop().await?;
209 info!("Service {service_name} has been stopped successfully.");
210 Ok(())
211 }
212 ServiceStatus::Stopped => {
213 debug!("Service {service_name} was already stopped");
214 if self.verbosity != VerbosityLevel::Minimal {
215 println!("{} Service {service_name} was already stopped", "✓".green(),);
216 }
217 Ok(())
218 }
219 }
220 }
221
222 pub async fn remove(&mut self, keep_directories: bool) -> Result<()> {
223 let service_name = self.service.name().await;
224 info!("Removing the {service_name} service");
225 if let ServiceStatus::Running = self.service.status().await {
226 if self
227 .service_control
228 .get_process_pid(&self.service.bin_path().await)
229 .is_ok()
230 {
231 error!("Service {service_name} is already running. Stop it before removing it",);
232 return Err(Error::ServiceAlreadyRunning(vec![service_name]));
233 } else {
234 self.service.on_stop().await?;
237 error!(
238 "The service: {service_name} was marked as running but it had actually stopped. You may want to check the logs for errors before removing it. To remove the service, run the command again."
239 );
240 return Err(Error::ServiceStatusMismatch {
241 expected: ServiceStatus::Running,
242 });
243 }
244 }
245
246 match self
247 .service_control
248 .uninstall(&service_name, self.service.is_user_mode().await)
249 {
250 Ok(()) => {
251 debug!("Service {service_name} has been uninstalled");
252 }
253 Err(err) => match err {
254 ServiceError::ServiceRemovedManually(name) => {
255 warn!(
256 "The user appears to have removed the {name} service manually. Skipping the error.",
257 );
258 if self.verbosity != VerbosityLevel::Minimal {
263 println!("The user appears to have removed the {name} service manually");
264 }
265 }
266 ServiceError::ServiceDoesNotExists(name) => {
267 warn!(
268 "The service {name} has most probably been removed already, it does not exists. Skipping the error."
269 );
270 }
271 _ => {
272 error!("Error uninstalling the service: {err}");
273 return Err(err.into());
274 }
275 },
276 }
277
278 if !keep_directories {
279 debug!("Removing data and log directories for {service_name}");
280 let data_dir_path = self.service.data_dir_path().await;
283 if data_dir_path.exists() {
284 debug!("Removing data directory {data_dir_path:?}");
285 std::fs::remove_dir_all(data_dir_path)?;
286 }
287 let log_dir_path = self.service.log_dir_path().await;
288 if log_dir_path.exists() {
289 debug!("Removing log directory {log_dir_path:?}");
290 std::fs::remove_dir_all(log_dir_path)?;
291 }
292 }
293
294 self.service.on_remove().await;
295 info!("Service {service_name} has been removed successfully.");
296
297 if self.verbosity != VerbosityLevel::Minimal {
298 println!("{} Service {service_name} was removed", "✓".green());
299 }
300
301 Ok(())
302 }
303
304 pub async fn upgrade(&mut self, options: UpgradeOptions) -> Result<UpgradeResult> {
305 let current_version = Version::parse(&self.service.version().await)?;
306 if !options.force
307 && (current_version == options.target_version
308 || options.target_version < current_version)
309 {
310 info!(
311 "The service {} is already at the latest version. No upgrade is required.",
312 self.service.name().await
313 );
314 return Ok(UpgradeResult::NotRequired);
315 }
316
317 debug!("Stopping the service and copying the binary");
318 self.stop().await?;
319 std::fs::copy(
320 options.clone().target_bin_path,
321 self.service.bin_path().await,
322 )?;
323
324 self.service_control.uninstall(
325 &self.service.name().await,
326 self.service.is_user_mode().await,
327 )?;
328 self.service_control.install(
329 self.service
330 .build_upgrade_install_context(options.clone())
331 .await?,
332 self.service.is_user_mode().await,
333 )?;
334
335 if options.start_service {
336 match self.start().await {
337 Ok(start_duration) => start_duration,
338 Err(err) => {
339 self.service
340 .set_version(&options.target_version.to_string())
341 .await;
342 info!("The service has been upgraded but could not be started: {err}");
343 return Ok(UpgradeResult::UpgradedButNotStarted(
344 current_version.to_string(),
345 options.target_version.to_string(),
346 err.to_string(),
347 ));
348 }
349 }
350 }
351 self.service
352 .set_version(&options.target_version.to_string())
353 .await;
354
355 if options.force {
356 Ok(UpgradeResult::Forced(
357 current_version.to_string(),
358 options.target_version.to_string(),
359 ))
360 } else {
361 Ok(UpgradeResult::Upgraded(
362 current_version.to_string(),
363 options.target_version.to_string(),
364 ))
365 }
366 }
367}
368
369pub async fn status_report(
370 node_registry: &NodeRegistryManager,
371 service_control: &dyn ServiceControl,
372 detailed_view: bool,
373 output_json: bool,
374 fail: bool,
375 is_local_network: bool,
376) -> Result<()> {
377 refresh_node_registry(
378 node_registry.clone(),
379 service_control,
380 !output_json,
381 is_local_network,
382 VerbosityLevel::Normal,
383 )
384 .await?;
385
386 if output_json {
387 let json = serde_json::to_string_pretty(&node_registry.to_status_summary().await)?;
388 println!("{json}");
389 } else if detailed_view {
390 for node in node_registry.nodes.read().await.iter() {
391 let node = node.read().await;
392 print_banner(&format!(
393 "{} - {}",
394 &node.service_name,
395 format_status_without_colour(&node.status)
396 ));
397 println!("Version: {}", node.version);
398 println!(
399 "Peer ID: {}",
400 node.peer_id.map_or("-".to_string(), |p| p.to_string())
401 );
402 println!("RPC Socket: {}", node.rpc_socket_addr);
403 println!("Listen Addresses: {:?}", node.listen_addr);
404 println!(
405 "PID: {}",
406 node.pid.map_or("-".to_string(), |p| p.to_string())
407 );
408 if node.status == ServiceStatus::Stopped
409 && let Some(failure_reason) = node.get_critical_failure()
410 {
411 println!(
412 "Failure reason: [{}] {}",
413 failure_reason.0, failure_reason.1
414 );
415 }
416 println!("Data path: {}", node.data_dir_path.to_string_lossy());
417 println!("Log path: {}", node.log_dir_path.to_string_lossy());
418 println!("Bin path: {}", node.antnode_path.to_string_lossy());
419 println!(
420 "Connected peers: {}",
421 node.connected_peers
422 .as_ref()
423 .map_or("-".to_string(), |p| p.len().to_string())
424 );
425 println!(
426 "Reward balance: {}",
427 node.reward_balance
428 .map_or("-".to_string(), |b| b.to_string())
429 );
430 println!("Rewards address: {}", node.rewards_address);
431 println!();
432 }
433
434 if let Some(daemon) = node_registry.daemon.read().await.as_ref() {
435 let daemon = daemon.read().await;
436 print_banner(&format!(
437 "{} - {}",
438 &daemon.service_name,
439 format_status(&daemon.status)
440 ));
441 println!("Version: {}", daemon.version);
442 println!("Bin path: {}", daemon.daemon_path.to_string_lossy());
443 }
444 } else {
445 println!(
446 "{:<18} {:<52} {:<7} {:>15} {:<}",
447 "Service Name", "Peer ID", "Status", "Connected Peers", "Failure"
448 );
449
450 for node in node_registry.nodes.read().await.iter() {
451 let node = node.read().await;
452
453 if node.status == ServiceStatus::Removed {
454 continue;
455 }
456
457 let peer_id = node.peer_id.map_or("-".to_string(), |p| p.to_string());
458 let connected_peers = node
459 .connected_peers
460 .clone()
461 .map_or("-".to_string(), |p| p.len().to_string());
462 let failure_reason = if node.status == ServiceStatus::Stopped {
463 node.get_critical_failure()
464 .map_or("-".to_string(), |(_time, reason)| reason)
465 } else {
466 "-".to_string()
467 };
468 println!(
469 "{:<18} {:<52} {:<7} {:>15} {:<}",
470 node.service_name,
471 peer_id,
472 format_status(&node.status),
473 connected_peers,
474 failure_reason
475 );
476 }
477 if let Some(daemon) = node_registry.daemon.read().await.as_ref() {
478 let daemon = daemon.read().await;
479 println!(
480 "{:<18} {:<52} {:<7} {:>15} {:>15}",
481 daemon.service_name,
482 "-",
483 format_status(&daemon.status),
484 "-",
485 "-"
486 );
487 }
488 }
489
490 if fail {
491 let mut non_running_services = Vec::new();
492 for node in node_registry.nodes.read().await.iter() {
493 let node = node.read().await;
494 if node.status != ServiceStatus::Running {
495 non_running_services.push(node.service_name.clone());
496 }
497 }
498
499 if non_running_services.is_empty() {
500 info!("Fail is set to true, but all services are running.");
501 } else {
502 error!(
503 "One or more nodes are not in a running state: {non_running_services:?}
504 "
505 );
506
507 return Err(Error::ServiceNotRunning(non_running_services));
508 }
509 }
510
511 Ok(())
512}
513
514pub async fn refresh_node_registry(
528 node_registry: NodeRegistryManager,
529 service_control: &dyn ServiceControl,
530 full_refresh: bool,
531 is_local_network: bool,
532 verbosity: VerbosityLevel,
533) -> Result<()> {
534 info!("Refreshing the node registry");
538 let pb = if verbosity != VerbosityLevel::Minimal {
539 let total_nodes = node_registry.nodes.read().await.len() as u64;
540 let pb = ProgressBar::new(total_nodes);
541 pb.set_style(
542 ProgressStyle::default_bar()
543 .template("{msg} {spinner:.green} [{bar:40.cyan/blue}] ({percent}%)")
544 .unwrap_or_else(|_e| {
545 ProgressStyle::default_bar()
547 })
548 .progress_chars("#>-"),
549 );
550 pb.set_message("Refreshing the node registry");
551 Some(pb)
552 } else {
553 None
554 };
555
556 for node in node_registry.nodes.read().await.iter() {
558 node.write().await.reward_balance = None;
563
564 let mut rpc_client = RpcClient::from_socket_addr(node.read().await.rpc_socket_addr);
565 rpc_client.set_max_attempts(1);
566 let service = NodeService::new(Arc::clone(node), Box::new(rpc_client.clone()));
567 let service_name = service.service_data.read().await.service_name.clone();
568
569 if is_local_network {
570 match rpc_client.node_info().await {
575 Ok(info) => {
576 let pid = info.pid;
577 debug!("local node {service_name} is running with PID {pid}",);
578 service.on_start(Some(pid), full_refresh).await?;
579 }
580 Err(_) => {
581 debug!("Failed to retrieve PID for local node {service_name}",);
582 service.on_stop().await?;
583 }
584 }
585 } else {
586 match service_control.get_process_pid(&service.bin_path().await) {
587 Ok(pid) => {
588 debug!("{service_name} is running with PID {pid}",);
589 service.on_start(Some(pid), full_refresh).await?;
590 }
591 Err(_) => {
592 match service.status().await {
593 ServiceStatus::Added => {
594 debug!("{service_name} has not been started since it was installed");
598 }
599 ServiceStatus::Removed => {
600 debug!("{service_name} has been removed");
603 }
604 _ => {
605 debug!("Failed to retrieve PID for {service_name}");
606 service.on_stop().await?;
607 }
608 }
609 }
610 }
611 }
612
613 if let Some(ref pb) = pb {
614 pb.inc(1);
615 }
616 }
617
618 if let Some(pb) = pb {
619 pb.finish_and_clear();
620 }
621
622 info!("Node registry refresh complete!");
623
624 Ok(())
625}
626
627pub fn print_banner(text: &str) {
628 let padding = 2;
629 let text_width = text.len() + padding * 2;
630 let border_chars = 2;
631 let total_width = text_width + border_chars;
632 let top_bottom = "═".repeat(total_width);
633
634 println!("╔{top_bottom}╗");
635 println!("║ {text:^text_width$} ║");
636 println!("╚{top_bottom}╝");
637}
638
639fn format_status(status: &ServiceStatus) -> String {
640 match status {
641 ServiceStatus::Running => "RUNNING".green().to_string(),
642 ServiceStatus::Stopped => "STOPPED".red().to_string(),
643 ServiceStatus::Added => "ADDED".yellow().to_string(),
644 ServiceStatus::Removed => "REMOVED".red().to_string(),
645 }
646}
647
648fn format_status_without_colour(status: &ServiceStatus) -> String {
649 match status {
650 ServiceStatus::Running => "RUNNING".to_string(),
651 ServiceStatus::Stopped => "STOPPED".to_string(),
652 ServiceStatus::Added => "ADDED".to_string(),
653 ServiceStatus::Removed => "REMOVED".to_string(),
654 }
655}
656
657#[cfg(test)]
658mod tests {
659 use super::*;
660 use ant_bootstrap::InitialPeersConfig;
661 use ant_evm::{AttoTokens, CustomNetwork, EvmNetwork, RewardsAddress};
662 use ant_logging::LogFormat;
663 use ant_service_management::{
664 UpgradeOptions, UpgradeResult,
665 error::{Error as ServiceControlError, Result as ServiceControlResult},
666 node::{NODE_SERVICE_DATA_SCHEMA_LATEST, NodeService, NodeServiceData},
667 rpc::{NetworkInfo, NodeInfo, RecordAddress, RpcActions},
668 };
669 use assert_fs::prelude::*;
670 use assert_matches::assert_matches;
671 use async_trait::async_trait;
672 use color_eyre::eyre::Result;
673 use libp2p_identity::PeerId;
674 use mockall::{mock, predicate::*};
675 use predicates::prelude::*;
676 use service_manager::ServiceInstallCtx;
677 use std::{
678 ffi::OsString,
679 net::{IpAddr, Ipv4Addr, SocketAddr},
680 path::{Path, PathBuf},
681 str::FromStr,
682 sync::Arc,
683 time::Duration,
684 };
685 use tokio::sync::RwLock;
686
687 mock! {
688 pub RpcClient {}
689 #[async_trait]
690 impl RpcActions for RpcClient {
691 async fn node_info(&self) -> ServiceControlResult<NodeInfo>;
692 async fn network_info(&self) -> ServiceControlResult<NetworkInfo>;
693 async fn record_addresses(&self) -> ServiceControlResult<Vec<RecordAddress>>;
694 async fn node_restart(&self, delay_millis: u64, retain_peer_id: bool) -> ServiceControlResult<()>;
695 async fn node_stop(&self, delay_millis: u64) -> ServiceControlResult<()>;
696 async fn node_update(&self, delay_millis: u64) -> ServiceControlResult<()>;
697 async fn is_node_connected_to_network(&self, timeout: std::time::Duration) -> ServiceControlResult<()>;
698 async fn update_log_level(&self, log_levels: String) -> ServiceControlResult<()>;
699 }
700 }
701
702 mock! {
703 pub ServiceControl {}
704 impl ServiceControl for ServiceControl {
705 fn create_service_user(&self, username: &str) -> ServiceControlResult<()>;
706 fn get_available_port(&self) -> ServiceControlResult<u16>;
707 fn install(&self, install_ctx: ServiceInstallCtx, user_mode: bool) -> ServiceControlResult<()>;
708 fn get_process_pid(&self, bin_path: &Path) -> ServiceControlResult<u32>;
709 fn start(&self, service_name: &str, user_mode: bool) -> ServiceControlResult<()>;
710 fn stop(&self, service_name: &str, user_mode: bool) -> ServiceControlResult<()>;
711 fn uninstall(&self, service_name: &str, user_mode: bool) -> ServiceControlResult<()>;
712 fn wait(&self, delay: u64);
713 }
714 }
715
716 #[tokio::test]
717 async fn start_should_start_a_newly_installed_service() -> Result<()> {
718 let mut mock_service_control = MockServiceControl::new();
719 let mut mock_rpc_client = MockRpcClient::new();
720
721 mock_service_control
722 .expect_start()
723 .with(eq("antnode1"), eq(false))
724 .times(1)
725 .returning(|_, _| Ok(()));
726 mock_service_control
727 .expect_wait()
728 .with(eq(3000))
729 .times(1)
730 .returning(|_| ());
731 mock_service_control
732 .expect_get_process_pid()
733 .with(eq(PathBuf::from("/var/antctl/services/antnode1/antnode")))
734 .times(1)
735 .returning(|_| Ok(1000));
736
737 mock_rpc_client.expect_node_info().times(1).returning(|| {
738 Ok(NodeInfo {
739 pid: 1000,
740 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
741 data_path: PathBuf::from("/var/antctl/services/antnode1"),
742 log_path: PathBuf::from("/var/log/antnode/antnode1"),
743 version: "0.98.1".to_string(),
744 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
746 })
747 });
748 mock_rpc_client
749 .expect_network_info()
750 .times(1)
751 .returning(|| {
752 Ok(NetworkInfo {
753 connected_peers: vec![PeerId::from_str(
754 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
755 )?],
756 listeners: Vec::new(),
757 })
758 });
759
760 let service_data = NodeServiceData {
761 alpha: false,
762 auto_restart: false,
763 connected_peers: None,
764 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
765 evm_network: EvmNetwork::Custom(CustomNetwork {
766 rpc_url_http: "http://localhost:8545".parse()?,
767 payment_token_address: RewardsAddress::from_str(
768 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
769 )?,
770 data_payments_address: RewardsAddress::from_str(
771 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
772 )?,
773 }),
774 relay: false,
775 initial_peers_config: InitialPeersConfig::default(),
776 listen_addr: None,
777 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
778 log_format: None,
779 max_archived_log_files: None,
780 max_log_files: None,
781 metrics_port: None,
782 network_id: None,
783 node_ip: None,
784 node_port: None,
785 number: 1,
786 peer_id: None,
787 pid: None,
788 rewards_address: RewardsAddress::from_str(
789 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
790 )?,
791 reward_balance: Some(AttoTokens::zero()),
792 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
793 antnode_path: PathBuf::from("/var/antctl/services/antnode1/antnode"),
794 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
795 service_name: "antnode1".to_string(),
796 status: ServiceStatus::Added,
797 no_upnp: false,
798 user: Some("ant".to_string()),
799 user_mode: false,
800 version: "0.98.1".to_string(),
801 write_older_cache_files: false,
802 };
803 let service_data = Arc::new(RwLock::new(service_data));
804 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
805
806 let mut service_manager = ServiceManager::new(
807 service,
808 Box::new(mock_service_control),
809 VerbosityLevel::Normal,
810 );
811
812 service_manager.start().await?;
813
814 let service_data = service_data.read().await;
815 assert_eq!(
816 service_data.connected_peers,
817 Some(vec![PeerId::from_str(
818 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
819 )?,])
820 );
821 assert_eq!(service_data.pid, Some(1000));
822 assert_eq!(
823 service_data.peer_id,
824 Some(PeerId::from_str(
825 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR"
826 )?)
827 );
828 assert_matches!(service_data.status, ServiceStatus::Running);
829
830 Ok(())
831 }
832
833 #[tokio::test]
834 async fn start_should_start_a_stopped_service() -> Result<()> {
835 let mut mock_service_control = MockServiceControl::new();
836 let mut mock_rpc_client = MockRpcClient::new();
837
838 mock_service_control
839 .expect_start()
840 .with(eq("antnode1"), eq(false))
841 .times(1)
842 .returning(|_, _| Ok(()));
843 mock_service_control
844 .expect_wait()
845 .with(eq(3000))
846 .times(1)
847 .returning(|_| ());
848 mock_service_control
849 .expect_get_process_pid()
850 .with(eq(PathBuf::from("/var/antctl/services/antnode1/antnode")))
851 .times(1)
852 .returning(|_| Ok(1000));
853
854 mock_rpc_client.expect_node_info().times(1).returning(|| {
855 Ok(NodeInfo {
856 pid: 1000,
857 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
858 data_path: PathBuf::from("/var/antctl/services/antnode1"),
859 log_path: PathBuf::from("/var/log/antnode/antnode1"),
860 version: "0.98.1".to_string(),
861 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
863 })
864 });
865 mock_rpc_client
866 .expect_network_info()
867 .times(1)
868 .returning(|| {
869 Ok(NetworkInfo {
870 connected_peers: Vec::new(),
871 listeners: Vec::new(),
872 })
873 });
874
875 let service_data = NodeServiceData {
876 alpha: false,
877 auto_restart: false,
878 connected_peers: None,
879 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
880 evm_network: EvmNetwork::Custom(CustomNetwork {
881 rpc_url_http: "http://localhost:8545".parse()?,
882 payment_token_address: RewardsAddress::from_str(
883 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
884 )?,
885 data_payments_address: RewardsAddress::from_str(
886 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
887 )?,
888 }),
889 relay: false,
890 initial_peers_config: InitialPeersConfig::default(),
891 listen_addr: None,
892 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
893 log_format: None,
894 max_archived_log_files: None,
895 max_log_files: None,
896 metrics_port: None,
897 network_id: None,
898 node_ip: None,
899 node_port: None,
900 number: 1,
901 peer_id: Some(PeerId::from_str(
902 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
903 )?),
904 pid: None,
905 rewards_address: RewardsAddress::from_str(
906 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
907 )?,
908 reward_balance: Some(AttoTokens::zero()),
909 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
910 antnode_path: PathBuf::from("/var/antctl/services/antnode1/antnode"),
911 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
912 service_name: "antnode1".to_string(),
913 status: ServiceStatus::Stopped,
914 no_upnp: false,
915 user: Some("ant".to_string()),
916 user_mode: false,
917 version: "0.98.1".to_string(),
918 write_older_cache_files: false,
919 };
920 let service_data = Arc::new(RwLock::new(service_data));
921 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
922
923 let mut service_manager = ServiceManager::new(
924 service,
925 Box::new(mock_service_control),
926 VerbosityLevel::Normal,
927 );
928
929 service_manager.start().await?;
930
931 let service_data = service_data.read().await;
932 assert_eq!(service_data.pid, Some(1000));
933 assert_eq!(
934 service_data.peer_id,
935 Some(PeerId::from_str(
936 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR"
937 )?)
938 );
939 assert_matches!(service_data.status, ServiceStatus::Running);
940
941 Ok(())
942 }
943
944 #[tokio::test]
945 async fn start_should_not_attempt_to_start_a_running_service() -> Result<()> {
946 let mut mock_service_control = MockServiceControl::new();
947 let mock_rpc_client = MockRpcClient::new();
948
949 mock_service_control
950 .expect_get_process_pid()
951 .with(eq(PathBuf::from("/var/antctl/services/antnode1/antnode")))
952 .times(1)
953 .returning(|_| Ok(100));
954
955 let service_data = NodeServiceData {
956 alpha: false,
957 auto_restart: false,
958 connected_peers: None,
959 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
960 evm_network: EvmNetwork::Custom(CustomNetwork {
961 rpc_url_http: "http://localhost:8545".parse()?,
962 payment_token_address: RewardsAddress::from_str(
963 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
964 )?,
965 data_payments_address: RewardsAddress::from_str(
966 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
967 )?,
968 }),
969 relay: false,
970 initial_peers_config: InitialPeersConfig::default(),
971 listen_addr: None,
972 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
973 log_format: None,
974 max_archived_log_files: None,
975 max_log_files: None,
976 metrics_port: None,
977 network_id: None,
978 node_ip: None,
979 node_port: None,
980 number: 1,
981 peer_id: Some(PeerId::from_str(
982 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
983 )?),
984 pid: Some(1000),
985 rewards_address: RewardsAddress::from_str(
986 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
987 )?,
988 reward_balance: Some(AttoTokens::zero()),
989 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
990 antnode_path: PathBuf::from("/var/antctl/services/antnode1/antnode"),
991 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
992 service_name: "antnode1".to_string(),
993 status: ServiceStatus::Running,
994 no_upnp: false,
995 user: Some("ant".to_string()),
996 user_mode: false,
997 version: "0.98.1".to_string(),
998 write_older_cache_files: false,
999 };
1000 let service_data = Arc::new(RwLock::new(service_data));
1001 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
1002
1003 let mut service_manager = ServiceManager::new(
1004 service,
1005 Box::new(mock_service_control),
1006 VerbosityLevel::Normal,
1007 );
1008
1009 service_manager.start().await?;
1010
1011 let service_data = service_data.read().await;
1012 assert_eq!(service_data.pid, Some(1000));
1013 assert_eq!(
1014 service_data.peer_id,
1015 Some(PeerId::from_str(
1016 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR"
1017 )?)
1018 );
1019 assert_matches!(service_data.status, ServiceStatus::Running);
1020
1021 Ok(())
1022 }
1023
1024 #[tokio::test]
1025 async fn start_should_start_a_service_marked_as_running_but_had_since_stopped() -> Result<()> {
1026 let mut mock_service_control = MockServiceControl::new();
1027 let mut mock_rpc_client = MockRpcClient::new();
1028
1029 mock_service_control
1030 .expect_get_process_pid()
1031 .with(eq(PathBuf::from("/var/antctl/services/antnode1/antnode")))
1032 .times(1)
1033 .returning(|_| {
1034 Err(ServiceError::ServiceProcessNotFound(
1035 "Could not find process at '/var/antctl/services/antnode1/antnode'".to_string(),
1036 ))
1037 });
1038 mock_service_control
1039 .expect_start()
1040 .with(eq("antnode1"), eq(false))
1041 .times(1)
1042 .returning(|_, _| Ok(()));
1043 mock_service_control
1044 .expect_wait()
1045 .with(eq(3000))
1046 .times(1)
1047 .returning(|_| ());
1048 mock_service_control
1049 .expect_get_process_pid()
1050 .with(eq(PathBuf::from("/var/antctl/services/antnode1/antnode")))
1051 .times(1)
1052 .returning(|_| Ok(1000));
1053
1054 mock_rpc_client.expect_node_info().times(1).returning(|| {
1055 Ok(NodeInfo {
1056 pid: 1000,
1057 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
1058 data_path: PathBuf::from("/var/antctl/services/antnode1"),
1059 log_path: PathBuf::from("/var/log/antnode/antnode1"),
1060 version: "0.98.1".to_string(),
1061 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
1063 })
1064 });
1065 mock_rpc_client
1066 .expect_network_info()
1067 .times(1)
1068 .returning(|| {
1069 Ok(NetworkInfo {
1070 connected_peers: Vec::new(),
1071 listeners: Vec::new(),
1072 })
1073 });
1074
1075 let service_data = NodeServiceData {
1076 alpha: false,
1077 auto_restart: false,
1078 connected_peers: None,
1079 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
1080 evm_network: EvmNetwork::Custom(CustomNetwork {
1081 rpc_url_http: "http://localhost:8545".parse()?,
1082 payment_token_address: RewardsAddress::from_str(
1083 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
1084 )?,
1085 data_payments_address: RewardsAddress::from_str(
1086 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
1087 )?,
1088 }),
1089 relay: false,
1090 initial_peers_config: InitialPeersConfig::default(),
1091 listen_addr: None,
1092 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
1093 log_format: None,
1094 max_archived_log_files: None,
1095 max_log_files: None,
1096 metrics_port: None,
1097 network_id: None,
1098 node_ip: None,
1099 node_port: None,
1100 number: 1,
1101 peer_id: Some(PeerId::from_str(
1102 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
1103 )?),
1104 pid: Some(1000),
1105 rewards_address: RewardsAddress::from_str(
1106 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
1107 )?,
1108 reward_balance: Some(AttoTokens::zero()),
1109 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
1110 antnode_path: PathBuf::from("/var/antctl/services/antnode1/antnode"),
1111 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
1112 service_name: "antnode1".to_string(),
1113 status: ServiceStatus::Running,
1114 no_upnp: false,
1115 user: Some("ant".to_string()),
1116 user_mode: false,
1117 version: "0.98.1".to_string(),
1118 write_older_cache_files: false,
1119 };
1120 let service_data = Arc::new(RwLock::new(service_data));
1121 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
1122
1123 let mut service_manager = ServiceManager::new(
1124 service,
1125 Box::new(mock_service_control),
1126 VerbosityLevel::Normal,
1127 );
1128
1129 service_manager.start().await?;
1130
1131 let service_data = service_data.read().await;
1132 assert_eq!(service_data.pid, Some(1000));
1133 assert_eq!(
1134 service_data.peer_id,
1135 Some(PeerId::from_str(
1136 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR"
1137 )?)
1138 );
1139 assert_matches!(service_data.status, ServiceStatus::Running);
1140
1141 Ok(())
1142 }
1143
1144 #[tokio::test]
1145 async fn start_should_return_an_error_if_the_process_was_not_found() -> Result<()> {
1146 let mut mock_service_control = MockServiceControl::new();
1147
1148 mock_service_control
1149 .expect_start()
1150 .with(eq("antnode1"), eq(false))
1151 .times(1)
1152 .returning(|_, _| Ok(()));
1153 mock_service_control
1154 .expect_wait()
1155 .with(eq(3000))
1156 .times(1)
1157 .returning(|_| ());
1158 mock_service_control
1159 .expect_get_process_pid()
1160 .with(eq(PathBuf::from("/var/antctl/services/antnode1/antnode")))
1161 .times(1)
1162 .returning(|_| {
1163 Err(ServiceControlError::ServiceProcessNotFound(
1164 "/var/antctl/services/antnode1/antnode".to_string(),
1165 ))
1166 });
1167
1168 let service_data = NodeServiceData {
1169 alpha: false,
1170 auto_restart: false,
1171 connected_peers: None,
1172 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
1173 evm_network: EvmNetwork::Custom(CustomNetwork {
1174 rpc_url_http: "http://localhost:8545".parse()?,
1175 payment_token_address: RewardsAddress::from_str(
1176 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
1177 )?,
1178 data_payments_address: RewardsAddress::from_str(
1179 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
1180 )?,
1181 }),
1182 relay: false,
1183 initial_peers_config: InitialPeersConfig::default(),
1184 listen_addr: None,
1185 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
1186 log_format: None,
1187 max_archived_log_files: None,
1188 max_log_files: None,
1189 metrics_port: None,
1190 network_id: None,
1191 node_ip: None,
1192 node_port: None,
1193 number: 1,
1194 peer_id: None,
1195 pid: None,
1196 rewards_address: RewardsAddress::from_str(
1197 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
1198 )?,
1199 reward_balance: Some(AttoTokens::zero()),
1200 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
1201 antnode_path: PathBuf::from("/var/antctl/services/antnode1/antnode"),
1202 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
1203 service_name: "antnode1".to_string(),
1204 status: ServiceStatus::Added,
1205 no_upnp: false,
1206 user: Some("ant".to_string()),
1207 user_mode: false,
1208 version: "0.98.1".to_string(),
1209 write_older_cache_files: false,
1210 };
1211 let service_data = Arc::new(RwLock::new(service_data));
1212 let service = NodeService::new(Arc::clone(&service_data), Box::new(MockRpcClient::new()));
1213 let mut service_manager = ServiceManager::new(
1214 service,
1215 Box::new(mock_service_control),
1216 VerbosityLevel::Normal,
1217 );
1218
1219 let result = service_manager.start().await;
1220 match result {
1221 Ok(_) => panic!("This test should have resulted in an error"),
1222 Err(e) => assert_eq!(
1223 "The PID of the process was not found after starting it.",
1224 e.to_string()
1225 ),
1226 }
1227
1228 Ok(())
1229 }
1230
1231 #[tokio::test]
1232 async fn start_should_start_a_user_mode_service() -> Result<()> {
1233 let mut mock_service_control = MockServiceControl::new();
1234 let mut mock_rpc_client = MockRpcClient::new();
1235
1236 mock_service_control
1237 .expect_start()
1238 .with(eq("antnode1"), eq(true))
1239 .times(1)
1240 .returning(|_, _| Ok(()));
1241 mock_service_control
1242 .expect_wait()
1243 .with(eq(3000))
1244 .times(1)
1245 .returning(|_| ());
1246 mock_service_control
1247 .expect_get_process_pid()
1248 .with(eq(PathBuf::from("/var/antctl/services/antnode1/antnode")))
1249 .times(1)
1250 .returning(|_| Ok(100));
1251
1252 mock_rpc_client.expect_node_info().times(1).returning(|| {
1253 Ok(NodeInfo {
1254 pid: 1000,
1255 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
1256 data_path: PathBuf::from("/var/antctl/services/antnode1"),
1257 log_path: PathBuf::from("/var/log/antnode/antnode1"),
1258 version: "0.98.1".to_string(),
1259 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
1261 })
1262 });
1263 mock_rpc_client
1264 .expect_network_info()
1265 .times(1)
1266 .returning(|| {
1267 Ok(NetworkInfo {
1268 connected_peers: Vec::new(),
1269 listeners: Vec::new(),
1270 })
1271 });
1272
1273 let service_data = NodeServiceData {
1274 alpha: false,
1275 auto_restart: false,
1276 connected_peers: None,
1277 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
1278 evm_network: EvmNetwork::Custom(CustomNetwork {
1279 rpc_url_http: "http://localhost:8545".parse()?,
1280 payment_token_address: RewardsAddress::from_str(
1281 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
1282 )?,
1283 data_payments_address: RewardsAddress::from_str(
1284 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
1285 )?,
1286 }),
1287 relay: false,
1288 initial_peers_config: InitialPeersConfig::default(),
1289 listen_addr: None,
1290 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
1291 log_format: None,
1292 max_archived_log_files: None,
1293 max_log_files: None,
1294 metrics_port: None,
1295 network_id: None,
1296 node_ip: None,
1297 node_port: None,
1298 number: 1,
1299 peer_id: None,
1300 pid: None,
1301 rewards_address: RewardsAddress::from_str(
1302 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
1303 )?,
1304 reward_balance: Some(AttoTokens::zero()),
1305 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
1306 antnode_path: PathBuf::from("/var/antctl/services/antnode1/antnode"),
1307 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
1308 service_name: "antnode1".to_string(),
1309 status: ServiceStatus::Added,
1310 no_upnp: false,
1311 user: Some("ant".to_string()),
1312 user_mode: true,
1313 version: "0.98.1".to_string(),
1314 write_older_cache_files: false,
1315 };
1316 let service_data = Arc::new(RwLock::new(service_data));
1317 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
1318
1319 let mut service_manager = ServiceManager::new(
1320 service,
1321 Box::new(mock_service_control),
1322 VerbosityLevel::Normal,
1323 );
1324
1325 service_manager.start().await?;
1326
1327 Ok(())
1328 }
1329
1330 #[tokio::test]
1331 async fn start_should_use_dynamic_startup_delay_if_set() -> Result<()> {
1332 let mut mock_service_control = MockServiceControl::new();
1333 let mut mock_rpc_client = MockRpcClient::new();
1334
1335 mock_service_control
1336 .expect_start()
1337 .with(eq("antnode1"), eq(false))
1338 .times(1)
1339 .returning(|_, _| Ok(()));
1340 mock_service_control
1341 .expect_wait()
1342 .with(eq(3000))
1343 .times(1)
1344 .returning(|_| ());
1345 mock_service_control
1346 .expect_get_process_pid()
1347 .with(eq(PathBuf::from("/var/antctl/services/antnode1/antnode")))
1348 .times(1)
1349 .returning(|_| Ok(1000));
1350 mock_rpc_client
1351 .expect_is_node_connected_to_network()
1352 .times(1)
1353 .returning(|_| Ok(()));
1354 mock_rpc_client.expect_node_info().times(1).returning(|| {
1355 Ok(NodeInfo {
1356 pid: 1000,
1357 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
1358 data_path: PathBuf::from("/var/antctl/services/antnode1"),
1359 log_path: PathBuf::from("/var/log/antnode/antnode1"),
1360 version: "0.98.1".to_string(),
1361 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
1363 })
1364 });
1365 mock_rpc_client
1366 .expect_network_info()
1367 .times(1)
1368 .returning(|| {
1369 Ok(NetworkInfo {
1370 connected_peers: vec![PeerId::from_str(
1371 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
1372 )?],
1373 listeners: Vec::new(),
1374 })
1375 });
1376
1377 let service_data = NodeServiceData {
1378 alpha: false,
1379 auto_restart: false,
1380 connected_peers: None,
1381 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
1382 evm_network: EvmNetwork::Custom(CustomNetwork {
1383 rpc_url_http: "http://localhost:8545".parse()?,
1384 payment_token_address: RewardsAddress::from_str(
1385 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
1386 )?,
1387 data_payments_address: RewardsAddress::from_str(
1388 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
1389 )?,
1390 }),
1391 relay: false,
1392 initial_peers_config: InitialPeersConfig::default(),
1393 listen_addr: None,
1394 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
1395 log_format: None,
1396 max_archived_log_files: None,
1397 max_log_files: None,
1398 metrics_port: None,
1399 network_id: None,
1400 node_ip: None,
1401 node_port: None,
1402 number: 1,
1403 peer_id: None,
1404 pid: None,
1405 rewards_address: RewardsAddress::from_str(
1406 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
1407 )?,
1408 reward_balance: Some(AttoTokens::zero()),
1409 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
1410 antnode_path: PathBuf::from("/var/antctl/services/antnode1/antnode"),
1411 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
1412 service_name: "antnode1".to_string(),
1413 status: ServiceStatus::Added,
1414 no_upnp: false,
1415 user: Some("ant".to_string()),
1416 user_mode: false,
1417 version: "0.98.1".to_string(),
1418 write_older_cache_files: false,
1419 };
1420 let service_data = Arc::new(RwLock::new(service_data));
1421 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client))
1422 .with_connection_timeout(Duration::from_secs(
1423 DEFAULT_NODE_STARTUP_CONNECTION_TIMEOUT_S,
1424 ));
1425 let mut service_manager = ServiceManager::new(
1426 service,
1427 Box::new(mock_service_control),
1428 VerbosityLevel::Normal,
1429 );
1430
1431 service_manager.start().await?;
1432
1433 Ok(())
1434 }
1435
1436 #[tokio::test]
1437 async fn stop_should_stop_a_running_service() -> Result<()> {
1438 let mut mock_service_control = MockServiceControl::new();
1439
1440 mock_service_control
1441 .expect_stop()
1442 .with(eq("antnode1"), eq(false))
1443 .times(1)
1444 .returning(|_, _| Ok(()));
1445 mock_service_control
1446 .expect_get_process_pid()
1447 .with(eq(PathBuf::from("/var/antctl/services/antnode1/antnode")))
1448 .times(1)
1449 .returning(|_| Ok(100));
1450
1451 let service_data = NodeServiceData {
1452 alpha: false,
1453 auto_restart: false,
1454 connected_peers: None,
1455 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
1456 evm_network: EvmNetwork::Custom(CustomNetwork {
1457 rpc_url_http: "http://localhost:8545".parse()?,
1458 payment_token_address: RewardsAddress::from_str(
1459 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
1460 )?,
1461 data_payments_address: RewardsAddress::from_str(
1462 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
1463 )?,
1464 }),
1465 relay: false,
1466 initial_peers_config: InitialPeersConfig::default(),
1467 listen_addr: None,
1468 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
1469 log_format: None,
1470 max_archived_log_files: None,
1471 max_log_files: None,
1472 metrics_port: None,
1473 network_id: None,
1474 node_ip: None,
1475 node_port: None,
1476 number: 1,
1477 peer_id: Some(PeerId::from_str(
1478 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
1479 )?),
1480 pid: Some(1000),
1481 rewards_address: RewardsAddress::from_str(
1482 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
1483 )?,
1484 reward_balance: Some(AttoTokens::zero()),
1485 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
1486 antnode_path: PathBuf::from("/var/antctl/services/antnode1/antnode"),
1487 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
1488 service_name: "antnode1".to_string(),
1489 status: ServiceStatus::Running,
1490 no_upnp: false,
1491 user: Some("ant".to_string()),
1492 user_mode: false,
1493 version: "0.98.1".to_string(),
1494 write_older_cache_files: false,
1495 };
1496 let service_data = Arc::new(RwLock::new(service_data));
1497 let service = NodeService::new(Arc::clone(&service_data), Box::new(MockRpcClient::new()));
1498 let mut service_manager = ServiceManager::new(
1499 service,
1500 Box::new(mock_service_control),
1501 VerbosityLevel::Normal,
1502 );
1503
1504 service_manager.stop().await?;
1505
1506 let service_data = service_data.read().await;
1507 assert_eq!(service_data.pid, None);
1508 assert_eq!(service_data.connected_peers, None);
1509 assert_matches!(service_data.status, ServiceStatus::Stopped);
1510 Ok(())
1511 }
1512
1513 #[tokio::test]
1514 async fn stop_should_not_return_error_for_attempt_to_stop_installed_service() -> Result<()> {
1515 let service_data = NodeServiceData {
1516 alpha: false,
1517 auto_restart: false,
1518 connected_peers: None,
1519 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
1520 evm_network: EvmNetwork::Custom(CustomNetwork {
1521 rpc_url_http: "http://localhost:8545".parse()?,
1522 payment_token_address: RewardsAddress::from_str(
1523 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
1524 )?,
1525 data_payments_address: RewardsAddress::from_str(
1526 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
1527 )?,
1528 }),
1529 relay: false,
1530 initial_peers_config: InitialPeersConfig::default(),
1531 listen_addr: None,
1532 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
1533 log_format: None,
1534 max_archived_log_files: None,
1535 max_log_files: None,
1536 metrics_port: None,
1537 network_id: None,
1538 node_ip: None,
1539 node_port: None,
1540 number: 1,
1541 peer_id: None,
1542 pid: None,
1543 rewards_address: RewardsAddress::from_str(
1544 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
1545 )?,
1546 reward_balance: Some(AttoTokens::zero()),
1547 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
1548 antnode_path: PathBuf::from("/var/antctl/services/antnode1/antnode"),
1549 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
1550 service_name: "antnode1".to_string(),
1551 status: ServiceStatus::Added,
1552 no_upnp: false,
1553 user: Some("ant".to_string()),
1554 user_mode: false,
1555 version: "0.98.1".to_string(),
1556 write_older_cache_files: false,
1557 };
1558 let service_data = Arc::new(RwLock::new(service_data));
1559 let service = NodeService::new(Arc::clone(&service_data), Box::new(MockRpcClient::new()));
1560 let mut service_manager = ServiceManager::new(
1561 service,
1562 Box::new(MockServiceControl::new()),
1563 VerbosityLevel::Normal,
1564 );
1565
1566 let result = service_manager.stop().await;
1567
1568 match result {
1569 Ok(()) => Ok(()),
1570 Err(_) => {
1571 panic!("The stop command should be idempotent and do nothing for an added service");
1572 }
1573 }
1574 }
1575
1576 #[tokio::test]
1577 async fn stop_should_return_ok_when_attempting_to_stop_service_that_was_already_stopped()
1578 -> Result<()> {
1579 let service_data = NodeServiceData {
1580 alpha: false,
1581 auto_restart: false,
1582 connected_peers: None,
1583 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
1584 evm_network: EvmNetwork::Custom(CustomNetwork {
1585 rpc_url_http: "http://localhost:8545".parse()?,
1586 payment_token_address: RewardsAddress::from_str(
1587 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
1588 )?,
1589 data_payments_address: RewardsAddress::from_str(
1590 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
1591 )?,
1592 }),
1593 relay: false,
1594 initial_peers_config: InitialPeersConfig::default(),
1595 listen_addr: None,
1596 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
1597 log_format: None,
1598 max_archived_log_files: None,
1599 max_log_files: None,
1600 metrics_port: None,
1601 network_id: None,
1602 node_ip: None,
1603 node_port: None,
1604 number: 1,
1605 peer_id: Some(PeerId::from_str(
1606 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
1607 )?),
1608 pid: None,
1609 rewards_address: RewardsAddress::from_str(
1610 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
1611 )?,
1612 reward_balance: Some(AttoTokens::zero()),
1613 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
1614 antnode_path: PathBuf::from("/var/antctl/services/antnode1/antnode"),
1615 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
1616 service_name: "antnode1".to_string(),
1617 status: ServiceStatus::Stopped,
1618 no_upnp: false,
1619 user: Some("ant".to_string()),
1620 user_mode: false,
1621 version: "0.98.1".to_string(),
1622 write_older_cache_files: false,
1623 };
1624 let service_data = Arc::new(RwLock::new(service_data));
1625 let service = NodeService::new(Arc::clone(&service_data), Box::new(MockRpcClient::new()));
1626 let mut service_manager = ServiceManager::new(
1627 service,
1628 Box::new(MockServiceControl::new()),
1629 VerbosityLevel::Normal,
1630 );
1631
1632 let result = service_manager.stop().await;
1633
1634 match result {
1635 Ok(()) => Ok(()),
1636 Err(_) => {
1637 panic!(
1638 "The stop command should be idempotent and do nothing for an stopped service"
1639 );
1640 }
1641 }
1642 }
1643
1644 #[tokio::test]
1645 async fn stop_should_return_ok_when_attempting_to_stop_a_removed_service() -> Result<()> {
1646 let service_data = NodeServiceData {
1647 alpha: false,
1648 auto_restart: false,
1649 connected_peers: None,
1650 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
1651 evm_network: EvmNetwork::Custom(CustomNetwork {
1652 rpc_url_http: "http://localhost:8545".parse()?,
1653 payment_token_address: RewardsAddress::from_str(
1654 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
1655 )?,
1656 data_payments_address: RewardsAddress::from_str(
1657 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
1658 )?,
1659 }),
1660 relay: false,
1661 initial_peers_config: InitialPeersConfig::default(),
1662 listen_addr: None,
1663 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
1664 log_format: None,
1665 max_archived_log_files: None,
1666 max_log_files: None,
1667 metrics_port: None,
1668 network_id: None,
1669 node_ip: None,
1670 node_port: None,
1671 number: 1,
1672 peer_id: None,
1673 pid: None,
1674 rewards_address: RewardsAddress::from_str(
1675 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
1676 )?,
1677 reward_balance: Some(AttoTokens::zero()),
1678 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
1679 antnode_path: PathBuf::from("/var/antctl/services/antnode1/antnode"),
1680 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
1681 service_name: "antnode1".to_string(),
1682 status: ServiceStatus::Removed,
1683 no_upnp: false,
1684 user: Some("ant".to_string()),
1685 user_mode: false,
1686 version: "0.98.1".to_string(),
1687 write_older_cache_files: false,
1688 };
1689 let service_data = Arc::new(RwLock::new(service_data));
1690 let service = NodeService::new(Arc::clone(&service_data), Box::new(MockRpcClient::new()));
1691 let mut service_manager = ServiceManager::new(
1692 service,
1693 Box::new(MockServiceControl::new()),
1694 VerbosityLevel::Normal,
1695 );
1696
1697 let result = service_manager.stop().await;
1698
1699 match result {
1700 Ok(()) => Ok(()),
1701 Err(_) => {
1702 panic!(
1703 "The stop command should be idempotent and do nothing for a removed service"
1704 );
1705 }
1706 }
1707 }
1708
1709 #[tokio::test]
1710 async fn stop_should_stop_a_user_mode_service() -> Result<()> {
1711 let mut mock_service_control = MockServiceControl::new();
1712
1713 mock_service_control
1714 .expect_stop()
1715 .with(eq("antnode1"), eq(true))
1716 .times(1)
1717 .returning(|_, _| Ok(()));
1718 mock_service_control
1719 .expect_get_process_pid()
1720 .with(eq(PathBuf::from("/var/antctl/services/antnode1/antnode")))
1721 .times(1)
1722 .returning(|_| Ok(100));
1723
1724 let service_data = NodeServiceData {
1725 alpha: false,
1726 auto_restart: false,
1727 connected_peers: None,
1728 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
1729 evm_network: EvmNetwork::Custom(CustomNetwork {
1730 rpc_url_http: "http://localhost:8545".parse()?,
1731 payment_token_address: RewardsAddress::from_str(
1732 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
1733 )?,
1734 data_payments_address: RewardsAddress::from_str(
1735 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
1736 )?,
1737 }),
1738 relay: false,
1739 listen_addr: None,
1740 initial_peers_config: InitialPeersConfig::default(),
1741 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
1742 log_format: None,
1743 max_archived_log_files: None,
1744 max_log_files: None,
1745 metrics_port: None,
1746 network_id: None,
1747 node_ip: None,
1748 node_port: None,
1749 number: 1,
1750 peer_id: Some(PeerId::from_str(
1751 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
1752 )?),
1753 pid: Some(1000),
1754 rewards_address: RewardsAddress::from_str(
1755 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
1756 )?,
1757 reward_balance: Some(AttoTokens::zero()),
1758 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
1759 antnode_path: PathBuf::from("/var/antctl/services/antnode1/antnode"),
1760 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
1761 service_name: "antnode1".to_string(),
1762 status: ServiceStatus::Running,
1763 no_upnp: false,
1764 user: None,
1765 user_mode: true,
1766 version: "0.98.1".to_string(),
1767 write_older_cache_files: false,
1768 };
1769 let service_data = Arc::new(RwLock::new(service_data));
1770 let service = NodeService::new(Arc::clone(&service_data), Box::new(MockRpcClient::new()));
1771 let mut service_manager = ServiceManager::new(
1772 service,
1773 Box::new(mock_service_control),
1774 VerbosityLevel::Normal,
1775 );
1776
1777 service_manager.stop().await?;
1778
1779 let service_data = service_data.read().await;
1780 assert_eq!(service_data.pid, None);
1781 assert_eq!(service_data.connected_peers, None);
1782 assert_matches!(service_data.status, ServiceStatus::Stopped);
1783 Ok(())
1784 }
1785
1786 #[tokio::test]
1787 async fn upgrade_should_upgrade_a_service_to_a_new_version() -> Result<()> {
1788 let current_version = "0.1.0";
1789 let target_version = "0.2.0";
1790
1791 let tmp_data_dir = assert_fs::TempDir::new()?;
1792 let current_install_dir = tmp_data_dir.child("antnode_install");
1793 current_install_dir.create_dir_all()?;
1794
1795 let current_node_bin = current_install_dir.child("antnode");
1796 current_node_bin.write_binary(b"fake antnode binary")?;
1797 let target_node_bin = tmp_data_dir.child("antnode");
1798 target_node_bin.write_binary(b"fake antnode binary")?;
1799
1800 let mut mock_service_control = MockServiceControl::new();
1801 let mut mock_rpc_client = MockRpcClient::new();
1802
1803 mock_service_control
1805 .expect_get_process_pid()
1806 .with(eq(current_node_bin.to_path_buf().clone()))
1807 .times(1)
1808 .returning(|_| Ok(1000));
1809 mock_service_control
1810 .expect_stop()
1811 .with(eq("antnode1"), eq(false))
1812 .times(1)
1813 .returning(|_, _| Ok(()));
1814
1815 mock_service_control
1817 .expect_uninstall()
1818 .with(eq("antnode1"), eq(false))
1819 .times(1)
1820 .returning(|_, _| Ok(()));
1821 mock_service_control
1822 .expect_install()
1823 .with(always(), always())
1824 .times(1)
1825 .returning(|_, _| Ok(()));
1826
1827 mock_service_control
1829 .expect_start()
1830 .with(eq("antnode1"), eq(false))
1831 .times(1)
1832 .returning(|_, _| Ok(()));
1833 mock_service_control
1834 .expect_wait()
1835 .with(eq(3000))
1836 .times(1)
1837 .returning(|_| ());
1838 mock_service_control
1839 .expect_get_process_pid()
1840 .with(eq(current_node_bin.to_path_buf().clone()))
1841 .times(1)
1842 .returning(|_| Ok(2000));
1843
1844 mock_rpc_client.expect_node_info().times(1).returning(|| {
1845 Ok(NodeInfo {
1846 pid: 2000,
1847 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
1848 data_path: PathBuf::from("/var/antctl/services/antnode1"),
1849 log_path: PathBuf::from("/var/log/antnode/antnode1"),
1850 version: target_version.to_string(),
1851 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
1853 })
1854 });
1855 mock_rpc_client
1856 .expect_network_info()
1857 .times(1)
1858 .returning(|| {
1859 Ok(NetworkInfo {
1860 connected_peers: Vec::new(),
1861 listeners: Vec::new(),
1862 })
1863 });
1864
1865 let service_data = NodeServiceData {
1866 alpha: false,
1867 auto_restart: false,
1868 connected_peers: None,
1869 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
1870 evm_network: EvmNetwork::Custom(CustomNetwork {
1871 rpc_url_http: "http://localhost:8545".parse()?,
1872 payment_token_address: RewardsAddress::from_str(
1873 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
1874 )?,
1875 data_payments_address: RewardsAddress::from_str(
1876 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
1877 )?,
1878 }),
1879 relay: false,
1880 initial_peers_config: InitialPeersConfig::default(),
1881 listen_addr: None,
1882 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
1883 log_format: None,
1884 max_archived_log_files: None,
1885 max_log_files: None,
1886 metrics_port: None,
1887 network_id: None,
1888 node_ip: None,
1889 node_port: None,
1890 number: 1,
1891 peer_id: Some(PeerId::from_str(
1892 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
1893 )?),
1894 pid: Some(1000),
1895 rewards_address: RewardsAddress::from_str(
1896 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
1897 )?,
1898 reward_balance: Some(AttoTokens::zero()),
1899 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
1900 antnode_path: current_node_bin.to_path_buf(),
1901 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
1902 service_name: "antnode1".to_string(),
1903 status: ServiceStatus::Running,
1904 no_upnp: false,
1905 user: Some("ant".to_string()),
1906 user_mode: false,
1907 version: current_version.to_string(),
1908 write_older_cache_files: false,
1909 };
1910 let service_data = Arc::new(RwLock::new(service_data));
1911 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
1912 let mut service_manager = ServiceManager::new(
1913 service,
1914 Box::new(mock_service_control),
1915 VerbosityLevel::Normal,
1916 );
1917
1918 let upgrade_result = service_manager
1919 .upgrade(UpgradeOptions {
1920 auto_restart: false,
1921 env_variables: None,
1922 force: false,
1923 start_service: true,
1924 target_bin_path: target_node_bin.to_path_buf(),
1925 target_version: Version::parse(target_version).unwrap(),
1926 })
1927 .await?;
1928
1929 match upgrade_result {
1930 UpgradeResult::Upgraded(old_version, new_version) => {
1931 assert_eq!(old_version, current_version);
1932 assert_eq!(new_version, target_version);
1933 }
1934 _ => panic!("Expected UpgradeResult::Upgraded but was {upgrade_result:#?}"),
1935 }
1936
1937 let service_data = service_data.read().await;
1938 assert_eq!(service_data.pid, Some(2000));
1939 assert_eq!(
1940 service_data.peer_id,
1941 Some(PeerId::from_str(
1942 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
1943 )?)
1944 );
1945 assert_eq!(service_data.version, target_version);
1946
1947 Ok(())
1948 }
1949
1950 #[tokio::test]
1951 async fn upgrade_should_not_be_required_if_target_is_less_than_current_version() -> Result<()> {
1952 let current_version = "0.2.0";
1953 let target_version = "0.1.0";
1954
1955 let tmp_data_dir = assert_fs::TempDir::new()?;
1956 let current_install_dir = tmp_data_dir.child("antnode_install");
1957 current_install_dir.create_dir_all()?;
1958
1959 let current_node_bin = current_install_dir.child("antnode");
1960 current_node_bin.write_binary(b"fake antnode binary")?;
1961 let target_node_bin = tmp_data_dir.child("antnode");
1962 target_node_bin.write_binary(b"fake antnode binary")?;
1963
1964 let mock_service_control = MockServiceControl::new();
1965 let mock_rpc_client = MockRpcClient::new();
1966
1967 let service_data = NodeServiceData {
1968 alpha: false,
1969 auto_restart: false,
1970 connected_peers: None,
1971 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
1972 evm_network: EvmNetwork::Custom(CustomNetwork {
1973 rpc_url_http: "http://localhost:8545".parse()?,
1974 payment_token_address: RewardsAddress::from_str(
1975 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
1976 )?,
1977 data_payments_address: RewardsAddress::from_str(
1978 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
1979 )?,
1980 }),
1981 relay: false,
1982 initial_peers_config: InitialPeersConfig::default(),
1983 listen_addr: None,
1984 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
1985 log_format: None,
1986 max_archived_log_files: None,
1987 max_log_files: None,
1988 metrics_port: None,
1989 network_id: None,
1990 node_ip: None,
1991 node_port: None,
1992 number: 1,
1993 peer_id: Some(PeerId::from_str(
1994 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
1995 )?),
1996 pid: Some(1000),
1997 rewards_address: RewardsAddress::from_str(
1998 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
1999 )?,
2000 reward_balance: Some(AttoTokens::zero()),
2001 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
2002 antnode_path: current_node_bin.to_path_buf(),
2003 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
2004 service_name: "antnode1".to_string(),
2005 status: ServiceStatus::Running,
2006 no_upnp: false,
2007 user: Some("ant".to_string()),
2008 user_mode: false,
2009 version: current_version.to_string(),
2010 write_older_cache_files: false,
2011 };
2012 let service_data = Arc::new(RwLock::new(service_data));
2013 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
2014
2015 let mut service_manager = ServiceManager::new(
2016 service,
2017 Box::new(mock_service_control),
2018 VerbosityLevel::Normal,
2019 );
2020
2021 let upgrade_result = service_manager
2022 .upgrade(UpgradeOptions {
2023 auto_restart: false,
2024 env_variables: None,
2025 force: false,
2026 start_service: true,
2027 target_bin_path: target_node_bin.to_path_buf(),
2028 target_version: Version::parse(target_version).unwrap(),
2029 })
2030 .await?;
2031
2032 assert_matches!(upgrade_result, UpgradeResult::NotRequired);
2033
2034 Ok(())
2035 }
2036
2037 #[tokio::test]
2038 async fn upgrade_should_downgrade_to_a_previous_version_if_force_is_used() -> Result<()> {
2039 let current_version = "0.1.0";
2040 let target_version = "0.2.0";
2041
2042 let tmp_data_dir = assert_fs::TempDir::new()?;
2043 let current_install_dir = tmp_data_dir.child("antnode_install");
2044 current_install_dir.create_dir_all()?;
2045
2046 let current_node_bin = current_install_dir.child("antnode");
2047 current_node_bin.write_binary(b"fake antnode binary")?;
2048 let target_node_bin = tmp_data_dir.child("antnode");
2049 target_node_bin.write_binary(b"fake antnode binary")?;
2050
2051 let mut mock_service_control = MockServiceControl::new();
2052 let mut mock_rpc_client = MockRpcClient::new();
2053
2054 mock_service_control
2056 .expect_get_process_pid()
2057 .with(eq(current_node_bin.to_path_buf().clone()))
2058 .times(1)
2059 .returning(|_| Ok(1000));
2060 mock_service_control
2061 .expect_stop()
2062 .with(eq("antnode1"), eq(false))
2063 .times(1)
2064 .returning(|_, _| Ok(()));
2065
2066 mock_service_control
2068 .expect_uninstall()
2069 .with(eq("antnode1"), eq(false))
2070 .times(1)
2071 .returning(|_, _| Ok(()));
2072 mock_service_control
2073 .expect_install()
2074 .with(always(), always())
2075 .times(1)
2076 .returning(|_, _| Ok(()));
2077
2078 mock_service_control
2080 .expect_start()
2081 .with(eq("antnode1"), eq(false))
2082 .times(1)
2083 .returning(|_, _| Ok(()));
2084 mock_service_control
2085 .expect_wait()
2086 .with(eq(3000))
2087 .times(1)
2088 .returning(|_| ());
2089 mock_service_control
2090 .expect_get_process_pid()
2091 .with(eq(current_node_bin.to_path_buf().clone()))
2092 .times(1)
2093 .returning(|_| Ok(2000));
2094
2095 mock_rpc_client.expect_node_info().times(1).returning(|| {
2096 Ok(NodeInfo {
2097 pid: 2000,
2098 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
2099 data_path: PathBuf::from("/var/antctl/services/antnode1"),
2100 log_path: PathBuf::from("/var/log/antnode/antnode1"),
2101 version: target_version.to_string(),
2102 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
2104 })
2105 });
2106 mock_rpc_client
2107 .expect_network_info()
2108 .times(1)
2109 .returning(|| {
2110 Ok(NetworkInfo {
2111 connected_peers: Vec::new(),
2112 listeners: Vec::new(),
2113 })
2114 });
2115
2116 let service_data = NodeServiceData {
2117 alpha: false,
2118 auto_restart: false,
2119 connected_peers: None,
2120 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
2121 evm_network: EvmNetwork::Custom(CustomNetwork {
2122 rpc_url_http: "http://localhost:8545".parse()?,
2123 payment_token_address: RewardsAddress::from_str(
2124 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
2125 )?,
2126 data_payments_address: RewardsAddress::from_str(
2127 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
2128 )?,
2129 }),
2130 relay: false,
2131 initial_peers_config: InitialPeersConfig::default(),
2132 listen_addr: None,
2133 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
2134 log_format: None,
2135 max_archived_log_files: None,
2136 max_log_files: None,
2137 metrics_port: None,
2138 network_id: None,
2139 node_ip: None,
2140 node_port: None,
2141 number: 1,
2142 peer_id: Some(PeerId::from_str(
2143 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
2144 )?),
2145 pid: Some(1000),
2146 rewards_address: RewardsAddress::from_str(
2147 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
2148 )?,
2149 reward_balance: Some(AttoTokens::zero()),
2150 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
2151 antnode_path: current_node_bin.to_path_buf(),
2152 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
2153 service_name: "antnode1".to_string(),
2154 status: ServiceStatus::Running,
2155 no_upnp: false,
2156 user: Some("ant".to_string()),
2157 user_mode: false,
2158 version: current_version.to_string(),
2159 write_older_cache_files: false,
2160 };
2161 let service_data = Arc::new(RwLock::new(service_data));
2162 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
2163
2164 let mut service_manager = ServiceManager::new(
2165 service,
2166 Box::new(mock_service_control),
2167 VerbosityLevel::Normal,
2168 );
2169
2170 let upgrade_result = service_manager
2171 .upgrade(UpgradeOptions {
2172 auto_restart: false,
2173 env_variables: None,
2174 force: true,
2175 start_service: true,
2176 target_bin_path: target_node_bin.to_path_buf(),
2177 target_version: Version::parse(target_version).unwrap(),
2178 })
2179 .await?;
2180
2181 match upgrade_result {
2182 UpgradeResult::Forced(old_version, new_version) => {
2183 assert_eq!(old_version, current_version);
2184 assert_eq!(new_version, target_version);
2185 }
2186 _ => panic!("Expected UpgradeResult::Forced but was {upgrade_result:#?}"),
2187 }
2188
2189 let service_data = service_data.read().await;
2190 assert_eq!(service_data.pid, Some(2000));
2191 assert_eq!(
2192 service_data.peer_id,
2193 Some(PeerId::from_str(
2194 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
2195 )?)
2196 );
2197 assert_eq!(service_data.version, target_version);
2198
2199 Ok(())
2200 }
2201
2202 #[tokio::test]
2203 async fn upgrade_should_upgrade_and_not_start_the_service() -> Result<()> {
2204 let current_version = "0.1.0";
2205 let target_version = "0.2.0";
2206
2207 let tmp_data_dir = assert_fs::TempDir::new()?;
2208 let current_install_dir = tmp_data_dir.child("antnode_install");
2209 current_install_dir.create_dir_all()?;
2210
2211 let current_node_bin = current_install_dir.child("antnode");
2212 current_node_bin.write_binary(b"fake antnode binary")?;
2213 let target_node_bin = tmp_data_dir.child("antnode");
2214 target_node_bin.write_binary(b"fake antnode binary")?;
2215
2216 let mut mock_service_control = MockServiceControl::new();
2217 let mut mock_rpc_client = MockRpcClient::new();
2218
2219 mock_service_control
2221 .expect_get_process_pid()
2222 .with(eq(current_node_bin.to_path_buf().clone()))
2223 .times(1)
2224 .returning(|_| Ok(1000));
2225 mock_service_control
2226 .expect_stop()
2227 .with(eq("antnode1"), eq(false))
2228 .times(1)
2229 .returning(|_, _| Ok(()));
2230
2231 mock_service_control
2233 .expect_uninstall()
2234 .with(eq("antnode1"), eq(false))
2235 .times(1)
2236 .returning(|_, _| Ok(()));
2237 mock_service_control
2238 .expect_install()
2239 .with(always(), always())
2240 .times(1)
2241 .returning(|_, _| Ok(()));
2242
2243 mock_service_control
2245 .expect_start()
2246 .with(eq("antnode1"), eq(false))
2247 .times(0)
2248 .returning(|_, _| Ok(()));
2249 mock_service_control
2250 .expect_wait()
2251 .with(eq(3000))
2252 .times(0)
2253 .returning(|_| ());
2254 mock_rpc_client.expect_node_info().times(0).returning(|| {
2255 Ok(NodeInfo {
2256 pid: 2000,
2257 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
2258 data_path: PathBuf::from("/var/antctl/services/antnode1"),
2259 log_path: PathBuf::from("/var/log/antnode/antnode1"),
2260 version: target_version.to_string(),
2261 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
2263 })
2264 });
2265 mock_rpc_client
2266 .expect_network_info()
2267 .times(0)
2268 .returning(|| {
2269 Ok(NetworkInfo {
2270 connected_peers: Vec::new(),
2271 listeners: Vec::new(),
2272 })
2273 });
2274
2275 let service_data = NodeServiceData {
2276 alpha: false,
2277 auto_restart: false,
2278 connected_peers: None,
2279 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
2280 evm_network: EvmNetwork::Custom(CustomNetwork {
2281 rpc_url_http: "http://localhost:8545".parse()?,
2282 payment_token_address: RewardsAddress::from_str(
2283 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
2284 )?,
2285 data_payments_address: RewardsAddress::from_str(
2286 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
2287 )?,
2288 }),
2289 relay: false,
2290 initial_peers_config: InitialPeersConfig::default(),
2291 listen_addr: None,
2292 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
2293 log_format: None,
2294 max_archived_log_files: None,
2295 max_log_files: None,
2296 metrics_port: None,
2297 network_id: None,
2298 node_ip: None,
2299 node_port: None,
2300 number: 1,
2301 peer_id: Some(PeerId::from_str(
2302 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
2303 )?),
2304 pid: Some(1000),
2305 rewards_address: RewardsAddress::from_str(
2306 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
2307 )?,
2308 reward_balance: Some(AttoTokens::zero()),
2309 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
2310 antnode_path: current_node_bin.to_path_buf(),
2311 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
2312 service_name: "antnode1".to_string(),
2313 status: ServiceStatus::Running,
2314 no_upnp: false,
2315 user: Some("ant".to_string()),
2316 user_mode: false,
2317 version: current_version.to_string(),
2318 write_older_cache_files: false,
2319 };
2320 let service_data = Arc::new(RwLock::new(service_data));
2321 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
2322
2323 let mut service_manager = ServiceManager::new(
2324 service,
2325 Box::new(mock_service_control),
2326 VerbosityLevel::Normal,
2327 );
2328
2329 let upgrade_result = service_manager
2330 .upgrade(UpgradeOptions {
2331 auto_restart: false,
2332 env_variables: None,
2333 force: false,
2334 start_service: false,
2335 target_bin_path: target_node_bin.to_path_buf(),
2336 target_version: Version::parse(target_version).unwrap(),
2337 })
2338 .await?;
2339
2340 match upgrade_result {
2341 UpgradeResult::Upgraded(old_version, new_version) => {
2342 assert_eq!(old_version, current_version);
2343 assert_eq!(new_version, target_version);
2344 }
2345 _ => panic!("Expected UpgradeResult::Upgraded but was {upgrade_result:#?}"),
2346 }
2347
2348 let service_data = service_data.read().await;
2349 assert_eq!(service_data.pid, None);
2350 assert_eq!(
2351 service_data.peer_id,
2352 Some(PeerId::from_str(
2353 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
2354 )?)
2355 );
2356 assert_eq!(service_data.version, target_version);
2357 assert_matches!(service_data.status, ServiceStatus::Stopped);
2358
2359 Ok(())
2360 }
2361
2362 #[tokio::test]
2363 async fn upgrade_should_return_upgraded_but_not_started_if_service_did_not_start() -> Result<()>
2364 {
2365 let current_version = "0.1.0";
2366 let target_version = "0.2.0";
2367
2368 let tmp_data_dir = assert_fs::TempDir::new()?;
2369 let current_install_dir = tmp_data_dir.child("antnode_install");
2370 current_install_dir.create_dir_all()?;
2371
2372 let current_node_bin = current_install_dir.child("antnode");
2373 current_node_bin.write_binary(b"fake antnode binary")?;
2374 let target_node_bin = tmp_data_dir.child("antnode");
2375 target_node_bin.write_binary(b"fake antnode binary")?;
2376
2377 let current_node_bin_str = current_node_bin.to_path_buf().to_string_lossy().to_string();
2378
2379 let mut mock_service_control = MockServiceControl::new();
2380
2381 mock_service_control
2383 .expect_get_process_pid()
2384 .with(eq(current_node_bin.to_path_buf().clone()))
2385 .times(1)
2386 .returning(|_| Ok(1000));
2387 mock_service_control
2388 .expect_stop()
2389 .with(eq("antnode1"), eq(false))
2390 .times(1)
2391 .returning(|_, _| Ok(()));
2392
2393 mock_service_control
2395 .expect_uninstall()
2396 .with(eq("antnode1"), eq(false))
2397 .times(1)
2398 .returning(|_, _| Ok(()));
2399 mock_service_control
2400 .expect_install()
2401 .with(always(), always())
2402 .times(1)
2403 .returning(|_, _| Ok(()));
2404
2405 mock_service_control
2407 .expect_start()
2408 .with(eq("antnode1"), eq(false))
2409 .times(1)
2410 .returning(|_, _| Ok(()));
2411 mock_service_control
2412 .expect_wait()
2413 .with(eq(3000))
2414 .times(1)
2415 .returning(|_| ());
2416 mock_service_control
2417 .expect_get_process_pid()
2418 .with(eq(current_node_bin.to_path_buf().clone()))
2419 .times(1)
2420 .returning(move |_| {
2421 Err(ServiceControlError::ServiceProcessNotFound(
2422 current_node_bin_str.clone(),
2423 ))
2424 });
2425
2426 let service_data = NodeServiceData {
2427 alpha: false,
2428 auto_restart: false,
2429 connected_peers: None,
2430 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
2431 evm_network: EvmNetwork::Custom(CustomNetwork {
2432 rpc_url_http: "http://localhost:8545".parse()?,
2433 payment_token_address: RewardsAddress::from_str(
2434 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
2435 )?,
2436 data_payments_address: RewardsAddress::from_str(
2437 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
2438 )?,
2439 }),
2440 relay: false,
2441 initial_peers_config: InitialPeersConfig::default(),
2442 listen_addr: None,
2443 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
2444 log_format: None,
2445 max_archived_log_files: None,
2446 max_log_files: None,
2447 metrics_port: None,
2448 network_id: None,
2449 node_ip: None,
2450 node_port: None,
2451 number: 1,
2452 peer_id: Some(PeerId::from_str(
2453 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
2454 )?),
2455 pid: Some(1000),
2456 rewards_address: RewardsAddress::from_str(
2457 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
2458 )?,
2459 reward_balance: Some(AttoTokens::zero()),
2460 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
2461 antnode_path: current_node_bin.to_path_buf(),
2462 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
2463 service_name: "antnode1".to_string(),
2464 status: ServiceStatus::Running,
2465 no_upnp: false,
2466 user: Some("ant".to_string()),
2467 user_mode: false,
2468 version: current_version.to_string(),
2469 write_older_cache_files: false,
2470 };
2471 let service_data = Arc::new(RwLock::new(service_data));
2472 let service = NodeService::new(Arc::clone(&service_data), Box::new(MockRpcClient::new()));
2473 let mut service_manager = ServiceManager::new(
2474 service,
2475 Box::new(mock_service_control),
2476 VerbosityLevel::Normal,
2477 );
2478
2479 let upgrade_result = service_manager
2480 .upgrade(UpgradeOptions {
2481 auto_restart: false,
2482 env_variables: None,
2483 force: false,
2484 start_service: true,
2485 target_bin_path: target_node_bin.to_path_buf(),
2486 target_version: Version::parse(target_version).unwrap(),
2487 })
2488 .await?;
2489
2490 match upgrade_result {
2491 UpgradeResult::UpgradedButNotStarted(old_version, new_version, _) => {
2492 assert_eq!(old_version, current_version);
2493 assert_eq!(new_version, target_version);
2494 }
2495 _ => {
2496 panic!("Expected UpgradeResult::UpgradedButNotStarted but was {upgrade_result:#?}")
2497 }
2498 }
2499
2500 Ok(())
2501 }
2502
2503 #[tokio::test]
2504 async fn upgrade_should_upgrade_a_service_in_user_mode() -> Result<()> {
2505 let current_version = "0.1.0";
2506 let target_version = "0.2.0";
2507
2508 let tmp_data_dir = assert_fs::TempDir::new()?;
2509 let current_install_dir = tmp_data_dir.child("antnode_install");
2510 current_install_dir.create_dir_all()?;
2511
2512 let current_node_bin = current_install_dir.child("antnode");
2513 current_node_bin.write_binary(b"fake antnode binary")?;
2514 let target_node_bin = tmp_data_dir.child("antnode");
2515 target_node_bin.write_binary(b"fake antnode binary")?;
2516
2517 let mut mock_service_control = MockServiceControl::new();
2518 let mut mock_rpc_client = MockRpcClient::new();
2519
2520 mock_service_control
2522 .expect_get_process_pid()
2523 .with(eq(current_node_bin.to_path_buf().clone()))
2524 .times(1)
2525 .returning(|_| Ok(1000));
2526 mock_service_control
2527 .expect_stop()
2528 .with(eq("antnode1"), eq(true))
2529 .times(1)
2530 .returning(|_, _| Ok(()));
2531
2532 mock_service_control
2534 .expect_uninstall()
2535 .with(eq("antnode1"), eq(true))
2536 .times(1)
2537 .returning(|_, _| Ok(()));
2538 mock_service_control
2539 .expect_install()
2540 .with(always(), eq(true))
2541 .times(1)
2542 .returning(|_, _| Ok(()));
2543
2544 mock_service_control
2546 .expect_start()
2547 .with(eq("antnode1"), eq(true))
2548 .times(1)
2549 .returning(|_, _| Ok(()));
2550 mock_service_control
2551 .expect_wait()
2552 .with(eq(3000))
2553 .times(1)
2554 .returning(|_| ());
2555 mock_service_control
2556 .expect_get_process_pid()
2557 .with(eq(current_node_bin.to_path_buf().clone()))
2558 .times(1)
2559 .returning(|_| Ok(2000));
2560
2561 mock_rpc_client.expect_node_info().times(1).returning(|| {
2562 Ok(NodeInfo {
2563 pid: 2000,
2564 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
2565 data_path: PathBuf::from("/var/antctl/services/antnode1"),
2566 log_path: PathBuf::from("/var/log/antnode/antnode1"),
2567 version: target_version.to_string(),
2568 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
2570 })
2571 });
2572 mock_rpc_client
2573 .expect_network_info()
2574 .times(1)
2575 .returning(|| {
2576 Ok(NetworkInfo {
2577 connected_peers: Vec::new(),
2578 listeners: Vec::new(),
2579 })
2580 });
2581
2582 let service_data = NodeServiceData {
2583 alpha: false,
2584 auto_restart: false,
2585 connected_peers: None,
2586 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
2587 evm_network: EvmNetwork::Custom(CustomNetwork {
2588 rpc_url_http: "http://localhost:8545".parse()?,
2589 payment_token_address: RewardsAddress::from_str(
2590 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
2591 )?,
2592 data_payments_address: RewardsAddress::from_str(
2593 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
2594 )?,
2595 }),
2596 relay: false,
2597 initial_peers_config: InitialPeersConfig::default(),
2598 listen_addr: None,
2599 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
2600 log_format: None,
2601 max_archived_log_files: None,
2602 max_log_files: None,
2603 metrics_port: None,
2604 network_id: None,
2605 node_ip: None,
2606 node_port: None,
2607 number: 1,
2608 peer_id: Some(PeerId::from_str(
2609 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
2610 )?),
2611 pid: Some(1000),
2612 rewards_address: RewardsAddress::from_str(
2613 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
2614 )?,
2615 reward_balance: Some(AttoTokens::zero()),
2616 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
2617 antnode_path: current_node_bin.to_path_buf(),
2618 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
2619 service_name: "antnode1".to_string(),
2620 status: ServiceStatus::Running,
2621 no_upnp: false,
2622 user: None,
2623 user_mode: true,
2624 version: current_version.to_string(),
2625 write_older_cache_files: false,
2626 };
2627 let service_data = Arc::new(RwLock::new(service_data));
2628 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
2629
2630 let mut service_manager = ServiceManager::new(
2631 service,
2632 Box::new(mock_service_control),
2633 VerbosityLevel::Normal,
2634 );
2635
2636 let upgrade_result = service_manager
2637 .upgrade(UpgradeOptions {
2638 auto_restart: false,
2639 env_variables: None,
2640 force: false,
2641 start_service: true,
2642 target_bin_path: target_node_bin.to_path_buf(),
2643 target_version: Version::parse(target_version).unwrap(),
2644 })
2645 .await?;
2646
2647 match upgrade_result {
2648 UpgradeResult::Upgraded(old_version, new_version) => {
2649 assert_eq!(old_version, current_version);
2650 assert_eq!(new_version, target_version);
2651 }
2652 _ => panic!("Expected UpgradeResult::Upgraded but was {upgrade_result:#?}"),
2653 }
2654
2655 let service_data = service_data.read().await;
2656 assert_eq!(service_data.pid, Some(2000));
2657 assert_eq!(
2658 service_data.peer_id,
2659 Some(PeerId::from_str(
2660 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
2661 )?)
2662 );
2663 assert_eq!(service_data.version, target_version);
2664
2665 Ok(())
2666 }
2667
2668 #[tokio::test]
2669 async fn upgrade_should_retain_the_first_flag() -> Result<()> {
2670 let current_version = "0.1.0";
2671 let target_version = "0.2.0";
2672
2673 let tmp_data_dir = assert_fs::TempDir::new()?;
2674 let current_install_dir = tmp_data_dir.child("antnode_install");
2675 current_install_dir.create_dir_all()?;
2676
2677 let current_node_bin = current_install_dir.child("antnode");
2678 current_node_bin.write_binary(b"fake antnode binary")?;
2679 let target_node_bin = tmp_data_dir.child("antnode");
2680 target_node_bin.write_binary(b"fake antnode binary")?;
2681
2682 let mut mock_service_control = MockServiceControl::new();
2683 let mut mock_rpc_client = MockRpcClient::new();
2684
2685 mock_service_control
2687 .expect_get_process_pid()
2688 .with(eq(current_node_bin.to_path_buf().clone()))
2689 .times(1)
2690 .returning(|_| Ok(1000));
2691 mock_service_control
2692 .expect_stop()
2693 .with(eq("antnode1"), eq(false))
2694 .times(1)
2695 .returning(|_, _| Ok(()));
2696
2697 mock_service_control
2699 .expect_uninstall()
2700 .with(eq("antnode1"), eq(false))
2701 .times(1)
2702 .returning(|_, _| Ok(()));
2703 mock_service_control
2704 .expect_install()
2705 .with(
2706 eq(ServiceInstallCtx {
2707 args: vec![
2708 OsString::from("--rpc"),
2709 OsString::from("127.0.0.1:8081"),
2710 OsString::from("--root-dir"),
2711 OsString::from("/var/antctl/services/antnode1"),
2712 OsString::from("--log-output-dest"),
2713 OsString::from("/var/log/antnode/antnode1"),
2714 OsString::from("--first"),
2715 OsString::from("--rewards-address"),
2716 OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"),
2717 OsString::from("evm-arbitrum-one"),
2718 ],
2719 autostart: false,
2720 contents: None,
2721 environment: None,
2722 label: "antnode1".parse()?,
2723 program: current_node_bin.to_path_buf(),
2724 username: Some("ant".to_string()),
2725 working_directory: None,
2726 disable_restart_on_failure: true,
2727 }),
2728 eq(false),
2729 )
2730 .times(1)
2731 .returning(|_, _| Ok(()));
2732
2733 mock_service_control
2735 .expect_start()
2736 .with(eq("antnode1"), eq(false))
2737 .times(1)
2738 .returning(|_, _| Ok(()));
2739 mock_service_control
2740 .expect_wait()
2741 .with(eq(3000))
2742 .times(1)
2743 .returning(|_| ());
2744 mock_service_control
2745 .expect_get_process_pid()
2746 .with(eq(current_node_bin.to_path_buf().clone()))
2747 .times(1)
2748 .returning(|_| Ok(100));
2749
2750 mock_rpc_client.expect_node_info().times(1).returning(|| {
2751 Ok(NodeInfo {
2752 pid: 2000,
2753 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
2754 data_path: PathBuf::from("/var/antctl/services/antnode1"),
2755 log_path: PathBuf::from("/var/log/antnode/antnode1"),
2756 version: target_version.to_string(),
2757 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
2759 })
2760 });
2761 mock_rpc_client
2762 .expect_network_info()
2763 .times(1)
2764 .returning(|| {
2765 Ok(NetworkInfo {
2766 connected_peers: Vec::new(),
2767 listeners: Vec::new(),
2768 })
2769 });
2770
2771 let service_data = NodeServiceData {
2772 alpha: false,
2773 auto_restart: false,
2774 connected_peers: None,
2775 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
2776 evm_network: EvmNetwork::ArbitrumOne,
2777 relay: false,
2778 initial_peers_config: InitialPeersConfig {
2779 first: true,
2780 addrs: vec![],
2781 network_contacts_url: vec![],
2782 local: false,
2783 ignore_cache: false,
2784 bootstrap_cache_dir: None,
2785 },
2786 listen_addr: None,
2787 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
2788 log_format: None,
2789 max_archived_log_files: None,
2790 max_log_files: None,
2791 metrics_port: None,
2792 network_id: None,
2793 node_ip: None,
2794 node_port: None,
2795 number: 1,
2796 peer_id: Some(PeerId::from_str(
2797 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
2798 )?),
2799 pid: Some(1000),
2800 rewards_address: RewardsAddress::from_str(
2801 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
2802 )?,
2803 reward_balance: Some(AttoTokens::zero()),
2804 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
2805 antnode_path: current_node_bin.to_path_buf(),
2806 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
2807 service_name: "antnode1".to_string(),
2808 status: ServiceStatus::Running,
2809 no_upnp: false,
2810 user: Some("ant".to_string()),
2811 user_mode: false,
2812 version: current_version.to_string(),
2813 write_older_cache_files: false,
2814 };
2815 let service_data = Arc::new(RwLock::new(service_data));
2816 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
2817
2818 let mut service_manager = ServiceManager::new(
2819 service,
2820 Box::new(mock_service_control),
2821 VerbosityLevel::Normal,
2822 );
2823
2824 service_manager
2825 .upgrade(UpgradeOptions {
2826 auto_restart: false,
2827 env_variables: None,
2828 force: false,
2829 start_service: true,
2830 target_bin_path: target_node_bin.to_path_buf(),
2831 target_version: Version::parse(target_version).unwrap(),
2832 })
2833 .await?;
2834
2835 let service_data = service_data.read().await;
2836 assert!(service_data.initial_peers_config.first);
2837
2838 Ok(())
2839 }
2840
2841 #[tokio::test]
2842 async fn upgrade_should_retain_the_peers_arg() -> Result<()> {
2843 let current_version = "0.1.0";
2844 let target_version = "0.2.0";
2845
2846 let tmp_data_dir = assert_fs::TempDir::new()?;
2847 let current_install_dir = tmp_data_dir.child("antnode_install");
2848 current_install_dir.create_dir_all()?;
2849
2850 let current_node_bin = current_install_dir.child("antnode");
2851 current_node_bin.write_binary(b"fake antnode binary")?;
2852 let target_node_bin = tmp_data_dir.child("antnode");
2853 target_node_bin.write_binary(b"fake antnode binary")?;
2854
2855 let mut mock_service_control = MockServiceControl::new();
2856 let mut mock_rpc_client = MockRpcClient::new();
2857
2858 mock_service_control
2860 .expect_get_process_pid()
2861 .with(eq(current_node_bin.to_path_buf().clone()))
2862 .times(1)
2863 .returning(|_| Ok(1000));
2864 mock_service_control
2865 .expect_stop()
2866 .with(eq("antnode1"), eq(false))
2867 .times(1)
2868 .returning(|_, _| Ok(()));
2869
2870 mock_service_control
2872 .expect_uninstall()
2873 .with(eq("antnode1"), eq(false))
2874 .times(1)
2875 .returning(|_, _| Ok(()));
2876 mock_service_control
2877 .expect_install()
2878 .with(
2879 eq(ServiceInstallCtx {
2880 args: vec![
2881 OsString::from("--rpc"),
2882 OsString::from("127.0.0.1:8081"),
2883 OsString::from("--root-dir"),
2884 OsString::from("/var/antctl/services/antnode1"),
2885 OsString::from("--log-output-dest"),
2886 OsString::from("/var/log/antnode/antnode1"),
2887 OsString::from("--peer"),
2888 OsString::from(
2889 "/ip4/127.0.0.1/tcp/8080/p2p/12D3KooWRBhwfeP2Y4TCx1SM6s9rUoHhR5STiGwxBhgFRcw3UERE"
2890 ),
2891 OsString::from("--rewards-address"),
2892 OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"),
2893 OsString::from("evm-arbitrum-one"),
2894 ],
2895 autostart: false,
2896 contents: None,
2897 environment: None,
2898 label: "antnode1".parse()?,
2899 program: current_node_bin.to_path_buf(),
2900 username: Some("ant".to_string()),
2901 working_directory: None,
2902 disable_restart_on_failure: true,
2903 }),
2904 eq(false),
2905 )
2906 .times(1)
2907 .returning(|_, _| Ok(()));
2908
2909 mock_service_control
2911 .expect_start()
2912 .with(eq("antnode1"), eq(false))
2913 .times(1)
2914 .returning(|_, _| Ok(()));
2915 mock_service_control
2916 .expect_wait()
2917 .with(eq(3000))
2918 .times(1)
2919 .returning(|_| ());
2920 mock_service_control
2921 .expect_get_process_pid()
2922 .with(eq(current_node_bin.to_path_buf().clone()))
2923 .times(1)
2924 .returning(|_| Ok(100));
2925
2926 mock_rpc_client.expect_node_info().times(1).returning(|| {
2927 Ok(NodeInfo {
2928 pid: 2000,
2929 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
2930 data_path: PathBuf::from("/var/antctl/services/antnode1"),
2931 log_path: PathBuf::from("/var/log/antnode/antnode1"),
2932 version: target_version.to_string(),
2933 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
2935 })
2936 });
2937 mock_rpc_client
2938 .expect_network_info()
2939 .times(1)
2940 .returning(|| {
2941 Ok(NetworkInfo {
2942 connected_peers: Vec::new(),
2943 listeners: Vec::new(),
2944 })
2945 });
2946
2947 let service_data = NodeServiceData {
2948 alpha: false,
2949 auto_restart: false,
2950 connected_peers: None,
2951 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
2952 evm_network: EvmNetwork::ArbitrumOne,
2953 relay: false,
2954 initial_peers_config: InitialPeersConfig {
2955 first: false,
2956 addrs: vec![
2957 "/ip4/127.0.0.1/tcp/8080/p2p/12D3KooWRBhwfeP2Y4TCx1SM6s9rUoHhR5STiGwxBhgFRcw3UERE"
2958 .parse()?,
2959 ],
2960 network_contacts_url: vec![],
2961 local: false,
2962 ignore_cache: false,
2963 bootstrap_cache_dir: None,
2964 },
2965 listen_addr: None,
2966 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
2967 log_format: None,
2968 max_archived_log_files: None,
2969 max_log_files: None,
2970 metrics_port: None,
2971 network_id: None,
2972 node_ip: None,
2973 node_port: None,
2974 number: 1,
2975 peer_id: Some(PeerId::from_str(
2976 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
2977 )?),
2978 pid: Some(1000),
2979 rewards_address: RewardsAddress::from_str(
2980 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
2981 )?,
2982 reward_balance: Some(AttoTokens::zero()),
2983 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
2984 antnode_path: current_node_bin.to_path_buf(),
2985 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST, service_name: "antnode1".to_string(),
2986 status: ServiceStatus::Running,
2987 no_upnp: false,
2988 user: Some("ant".to_string()),
2989 user_mode: false,
2990 version: current_version.to_string(),
2991 write_older_cache_files: false,
2992 };
2993 let service_data = Arc::new(RwLock::new(service_data));
2994 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
2995
2996 let mut service_manager = ServiceManager::new(
2997 service,
2998 Box::new(mock_service_control),
2999 VerbosityLevel::Normal,
3000 );
3001
3002 service_manager
3003 .upgrade(UpgradeOptions {
3004 auto_restart: false,
3005 env_variables: None,
3006 force: false,
3007 start_service: true,
3008 target_bin_path: target_node_bin.to_path_buf(),
3009 target_version: Version::parse(target_version).unwrap(),
3010 })
3011 .await?;
3012
3013 let service_data = service_data.read().await;
3014 assert!(!service_data.initial_peers_config.addrs.is_empty());
3015
3016 Ok(())
3017 }
3018
3019 #[tokio::test]
3020 async fn upgrade_should_retain_the_network_id_arg() -> Result<()> {
3021 let current_version = "0.1.0";
3022 let target_version = "0.2.0";
3023
3024 let tmp_data_dir = assert_fs::TempDir::new()?;
3025 let current_install_dir = tmp_data_dir.child("antnode_install");
3026 current_install_dir.create_dir_all()?;
3027
3028 let current_node_bin = current_install_dir.child("antnode");
3029 current_node_bin.write_binary(b"fake antnode binary")?;
3030 let target_node_bin = tmp_data_dir.child("antnode");
3031 target_node_bin.write_binary(b"fake antnode binary")?;
3032
3033 let mut mock_service_control = MockServiceControl::new();
3034 let mut mock_rpc_client = MockRpcClient::new();
3035
3036 mock_service_control
3038 .expect_get_process_pid()
3039 .with(eq(current_node_bin.to_path_buf().clone()))
3040 .times(1)
3041 .returning(|_| Ok(1000));
3042 mock_service_control
3043 .expect_stop()
3044 .with(eq("antnode1"), eq(false))
3045 .times(1)
3046 .returning(|_, _| Ok(()));
3047
3048 mock_service_control
3050 .expect_uninstall()
3051 .with(eq("antnode1"), eq(false))
3052 .times(1)
3053 .returning(|_, _| Ok(()));
3054 mock_service_control
3055 .expect_install()
3056 .with(
3057 eq(ServiceInstallCtx {
3058 args: vec![
3059 OsString::from("--rpc"),
3060 OsString::from("127.0.0.1:8081"),
3061 OsString::from("--root-dir"),
3062 OsString::from("/var/antctl/services/antnode1"),
3063 OsString::from("--log-output-dest"),
3064 OsString::from("/var/log/antnode/antnode1"),
3065 OsString::from("--network-id"),
3066 OsString::from("5"),
3067 OsString::from("--rewards-address"),
3068 OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"),
3069 OsString::from("evm-arbitrum-one"),
3070 ],
3071 autostart: false,
3072 contents: None,
3073 environment: None,
3074 label: "antnode1".parse()?,
3075 program: current_node_bin.to_path_buf(),
3076 username: Some("ant".to_string()),
3077 working_directory: None,
3078 disable_restart_on_failure: true,
3079 }),
3080 eq(false),
3081 )
3082 .times(1)
3083 .returning(|_, _| Ok(()));
3084
3085 mock_service_control
3087 .expect_start()
3088 .with(eq("antnode1"), eq(false))
3089 .times(1)
3090 .returning(|_, _| Ok(()));
3091 mock_service_control
3092 .expect_wait()
3093 .with(eq(3000))
3094 .times(1)
3095 .returning(|_| ());
3096 mock_service_control
3097 .expect_get_process_pid()
3098 .with(eq(current_node_bin.to_path_buf().clone()))
3099 .times(1)
3100 .returning(|_| Ok(100));
3101
3102 mock_rpc_client.expect_node_info().times(1).returning(|| {
3103 Ok(NodeInfo {
3104 pid: 2000,
3105 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
3106 data_path: PathBuf::from("/var/antctl/services/antnode1"),
3107 log_path: PathBuf::from("/var/log/antnode/antnode1"),
3108 version: target_version.to_string(),
3109 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
3111 })
3112 });
3113 mock_rpc_client
3114 .expect_network_info()
3115 .times(1)
3116 .returning(|| {
3117 Ok(NetworkInfo {
3118 connected_peers: Vec::new(),
3119 listeners: Vec::new(),
3120 })
3121 });
3122
3123 let service_data = NodeServiceData {
3124 alpha: false,
3125 auto_restart: false,
3126 connected_peers: None,
3127 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
3128 evm_network: EvmNetwork::ArbitrumOne,
3129 relay: false,
3130 initial_peers_config: Default::default(),
3131 listen_addr: None,
3132 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
3133 log_format: None,
3134 max_archived_log_files: None,
3135 max_log_files: None,
3136 metrics_port: None,
3137 network_id: Some(5),
3138 node_ip: None,
3139 node_port: None,
3140 number: 1,
3141 peer_id: Some(PeerId::from_str(
3142 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
3143 )?),
3144 pid: Some(1000),
3145 rewards_address: RewardsAddress::from_str(
3146 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
3147 )?,
3148 reward_balance: Some(AttoTokens::zero()),
3149 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
3150 antnode_path: current_node_bin.to_path_buf(),
3151 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
3152 service_name: "antnode1".to_string(),
3153 status: ServiceStatus::Running,
3154 no_upnp: false,
3155 user: Some("ant".to_string()),
3156 user_mode: false,
3157 version: current_version.to_string(),
3158 write_older_cache_files: false,
3159 };
3160 let service_data = Arc::new(RwLock::new(service_data));
3161 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
3162
3163 let mut service_manager = ServiceManager::new(
3164 service,
3165 Box::new(mock_service_control),
3166 VerbosityLevel::Normal,
3167 );
3168
3169 service_manager
3170 .upgrade(UpgradeOptions {
3171 auto_restart: false,
3172 env_variables: None,
3173 force: false,
3174 start_service: true,
3175 target_bin_path: target_node_bin.to_path_buf(),
3176 target_version: Version::parse(target_version).unwrap(),
3177 })
3178 .await?;
3179
3180 let service_data = service_data.read().await;
3181 assert_eq!(service_data.network_id, Some(5));
3182
3183 Ok(())
3184 }
3185
3186 #[tokio::test]
3187 async fn upgrade_should_retain_the_local_flag() -> Result<()> {
3188 let current_version = "0.1.0";
3189 let target_version = "0.2.0";
3190
3191 let tmp_data_dir = assert_fs::TempDir::new()?;
3192 let current_install_dir = tmp_data_dir.child("antnode_install");
3193 current_install_dir.create_dir_all()?;
3194
3195 let current_node_bin = current_install_dir.child("antnode");
3196 current_node_bin.write_binary(b"fake antnode binary")?;
3197 let target_node_bin = tmp_data_dir.child("antnode");
3198 target_node_bin.write_binary(b"fake antnode binary")?;
3199
3200 let mut mock_service_control = MockServiceControl::new();
3201 let mut mock_rpc_client = MockRpcClient::new();
3202
3203 mock_service_control
3205 .expect_get_process_pid()
3206 .with(eq(current_node_bin.to_path_buf().clone()))
3207 .times(1)
3208 .returning(|_| Ok(1000));
3209 mock_service_control
3210 .expect_stop()
3211 .with(eq("antnode1"), eq(false))
3212 .times(1)
3213 .returning(|_, _| Ok(()));
3214
3215 mock_service_control
3217 .expect_uninstall()
3218 .with(eq("antnode1"), eq(false))
3219 .times(1)
3220 .returning(|_, _| Ok(()));
3221 mock_service_control
3222 .expect_install()
3223 .with(
3224 eq(ServiceInstallCtx {
3225 args: vec![
3226 OsString::from("--rpc"),
3227 OsString::from("127.0.0.1:8081"),
3228 OsString::from("--root-dir"),
3229 OsString::from("/var/antctl/services/antnode1"),
3230 OsString::from("--log-output-dest"),
3231 OsString::from("/var/log/antnode/antnode1"),
3232 OsString::from("--local"),
3233 OsString::from("--rewards-address"),
3234 OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"),
3235 OsString::from("evm-arbitrum-one"),
3236 ],
3237 autostart: false,
3238 contents: None,
3239 environment: None,
3240 label: "antnode1".parse()?,
3241 program: current_node_bin.to_path_buf(),
3242 username: Some("ant".to_string()),
3243 working_directory: None,
3244 disable_restart_on_failure: true,
3245 }),
3246 eq(false),
3247 )
3248 .times(1)
3249 .returning(|_, _| Ok(()));
3250
3251 mock_service_control
3253 .expect_start()
3254 .with(eq("antnode1"), eq(false))
3255 .times(1)
3256 .returning(|_, _| Ok(()));
3257 mock_service_control
3258 .expect_wait()
3259 .with(eq(3000))
3260 .times(1)
3261 .returning(|_| ());
3262 mock_service_control
3263 .expect_get_process_pid()
3264 .with(eq(current_node_bin.to_path_buf().clone()))
3265 .times(1)
3266 .returning(|_| Ok(100));
3267
3268 mock_rpc_client.expect_node_info().times(1).returning(|| {
3269 Ok(NodeInfo {
3270 pid: 2000,
3271 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
3272 data_path: PathBuf::from("/var/antctl/services/antnode1"),
3273 log_path: PathBuf::from("/var/log/antnode/antnode1"),
3274 version: target_version.to_string(),
3275 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
3277 })
3278 });
3279 mock_rpc_client
3280 .expect_network_info()
3281 .times(1)
3282 .returning(|| {
3283 Ok(NetworkInfo {
3284 connected_peers: Vec::new(),
3285 listeners: Vec::new(),
3286 })
3287 });
3288
3289 let service_data = NodeServiceData {
3290 alpha: false,
3291 auto_restart: false,
3292 connected_peers: None,
3293 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
3294 evm_network: EvmNetwork::ArbitrumOne,
3295 relay: false,
3296 initial_peers_config: InitialPeersConfig {
3297 first: false,
3298 addrs: vec![],
3299 network_contacts_url: vec![],
3300 local: true,
3301 ignore_cache: false,
3302 bootstrap_cache_dir: None,
3303 },
3304 listen_addr: None,
3305 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
3306 log_format: None,
3307 max_archived_log_files: None,
3308 max_log_files: None,
3309 metrics_port: None,
3310 network_id: None,
3311 node_ip: None,
3312 node_port: None,
3313 number: 1,
3314 peer_id: Some(PeerId::from_str(
3315 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
3316 )?),
3317 pid: Some(1000),
3318 rewards_address: RewardsAddress::from_str(
3319 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
3320 )?,
3321 reward_balance: Some(AttoTokens::zero()),
3322 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
3323 antnode_path: current_node_bin.to_path_buf(),
3324 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
3325 service_name: "antnode1".to_string(),
3326 status: ServiceStatus::Running,
3327 no_upnp: false,
3328 user: Some("ant".to_string()),
3329 user_mode: false,
3330 version: current_version.to_string(),
3331 write_older_cache_files: false,
3332 };
3333 let service_data = Arc::new(RwLock::new(service_data));
3334 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
3335
3336 let mut service_manager = ServiceManager::new(
3337 service,
3338 Box::new(mock_service_control),
3339 VerbosityLevel::Normal,
3340 );
3341
3342 service_manager
3343 .upgrade(UpgradeOptions {
3344 auto_restart: false,
3345 env_variables: None,
3346 force: false,
3347 start_service: true,
3348 target_bin_path: target_node_bin.to_path_buf(),
3349 target_version: Version::parse(target_version).unwrap(),
3350 })
3351 .await?;
3352
3353 let service_data = service_data.read().await;
3354 assert!(service_data.initial_peers_config.local);
3355
3356 Ok(())
3357 }
3358
3359 #[tokio::test]
3360 async fn upgrade_should_retain_the_network_contacts_url_arg() -> Result<()> {
3361 let current_version = "0.1.0";
3362 let target_version = "0.2.0";
3363
3364 let tmp_data_dir = assert_fs::TempDir::new()?;
3365 let current_install_dir = tmp_data_dir.child("antnode_install");
3366 current_install_dir.create_dir_all()?;
3367
3368 let current_node_bin = current_install_dir.child("antnode");
3369 current_node_bin.write_binary(b"fake antnode binary")?;
3370 let target_node_bin = tmp_data_dir.child("antnode");
3371 target_node_bin.write_binary(b"fake antnode binary")?;
3372
3373 let mut mock_service_control = MockServiceControl::new();
3374 let mut mock_rpc_client = MockRpcClient::new();
3375
3376 mock_service_control
3378 .expect_get_process_pid()
3379 .with(eq(current_node_bin.to_path_buf().clone()))
3380 .times(1)
3381 .returning(|_| Ok(1000));
3382 mock_service_control
3383 .expect_stop()
3384 .with(eq("antnode1"), eq(false))
3385 .times(1)
3386 .returning(|_, _| Ok(()));
3387
3388 mock_service_control
3390 .expect_uninstall()
3391 .with(eq("antnode1"), eq(false))
3392 .times(1)
3393 .returning(|_, _| Ok(()));
3394 mock_service_control
3395 .expect_install()
3396 .with(
3397 eq(ServiceInstallCtx {
3398 args: vec![
3399 OsString::from("--rpc"),
3400 OsString::from("127.0.0.1:8081"),
3401 OsString::from("--root-dir"),
3402 OsString::from("/var/antctl/services/antnode1"),
3403 OsString::from("--log-output-dest"),
3404 OsString::from("/var/log/antnode/antnode1"),
3405 OsString::from("--network-contacts-url"),
3406 OsString::from("http://localhost:8080/contacts.json,http://localhost:8081/contacts.json"),
3407 OsString::from("--rewards-address"),
3408 OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"),
3409 OsString::from("evm-arbitrum-one"),
3410 ],
3411 autostart: false,
3412 contents: None,
3413 environment: None,
3414 label: "antnode1".parse()?,
3415 program: current_node_bin.to_path_buf(),
3416 username: Some("ant".to_string()),
3417 working_directory: None,
3418 disable_restart_on_failure: true,
3419 }),
3420 eq(false),
3421 )
3422 .times(1)
3423 .returning(|_, _| Ok(()));
3424
3425 mock_service_control
3427 .expect_start()
3428 .with(eq("antnode1"), eq(false))
3429 .times(1)
3430 .returning(|_, _| Ok(()));
3431 mock_service_control
3432 .expect_wait()
3433 .with(eq(3000))
3434 .times(1)
3435 .returning(|_| ());
3436 mock_service_control
3437 .expect_get_process_pid()
3438 .with(eq(current_node_bin.to_path_buf().clone()))
3439 .times(1)
3440 .returning(|_| Ok(100));
3441
3442 mock_rpc_client.expect_node_info().times(1).returning(|| {
3443 Ok(NodeInfo {
3444 pid: 2000,
3445 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
3446 data_path: PathBuf::from("/var/antctl/services/antnode1"),
3447 log_path: PathBuf::from("/var/log/antnode/antnode1"),
3448 version: target_version.to_string(),
3449 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
3451 })
3452 });
3453 mock_rpc_client
3454 .expect_network_info()
3455 .times(1)
3456 .returning(|| {
3457 Ok(NetworkInfo {
3458 connected_peers: Vec::new(),
3459 listeners: Vec::new(),
3460 })
3461 });
3462
3463 let service_data = NodeServiceData {
3464 alpha: false,
3465 auto_restart: false,
3466 connected_peers: None,
3467 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
3468 evm_network: EvmNetwork::ArbitrumOne,
3469 relay: false,
3470 initial_peers_config: InitialPeersConfig {
3471 first: false,
3472 addrs: vec![],
3473 network_contacts_url: vec![
3474 "http://localhost:8080/contacts.json".to_string(),
3475 "http://localhost:8081/contacts.json".to_string(),
3476 ],
3477 local: false,
3478 ignore_cache: false,
3479 bootstrap_cache_dir: None,
3480 },
3481 listen_addr: None,
3482 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
3483 log_format: None,
3484 max_archived_log_files: None,
3485 max_log_files: None,
3486 metrics_port: None,
3487 network_id: None,
3488 node_ip: None,
3489 node_port: None,
3490 number: 1,
3491 peer_id: Some(PeerId::from_str(
3492 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
3493 )?),
3494 pid: Some(1000),
3495 rewards_address: RewardsAddress::from_str(
3496 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
3497 )?,
3498 reward_balance: Some(AttoTokens::zero()),
3499 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
3500 antnode_path: current_node_bin.to_path_buf(),
3501 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
3502 service_name: "antnode1".to_string(),
3503 status: ServiceStatus::Running,
3504 no_upnp: false,
3505 user: Some("ant".to_string()),
3506 user_mode: false,
3507 version: current_version.to_string(),
3508 write_older_cache_files: false,
3509 };
3510 let service_data = Arc::new(RwLock::new(service_data));
3511 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
3512
3513 let mut service_manager = ServiceManager::new(
3514 service,
3515 Box::new(mock_service_control),
3516 VerbosityLevel::Normal,
3517 );
3518
3519 service_manager
3520 .upgrade(UpgradeOptions {
3521 auto_restart: false,
3522 env_variables: None,
3523 force: false,
3524 start_service: true,
3525 target_bin_path: target_node_bin.to_path_buf(),
3526 target_version: Version::parse(target_version).unwrap(),
3527 })
3528 .await?;
3529
3530 let service_data = service_data.read().await;
3531 assert_eq!(
3532 service_data.initial_peers_config.network_contacts_url.len(),
3533 2
3534 );
3535
3536 Ok(())
3537 }
3538
3539 #[tokio::test]
3540 async fn upgrade_should_retain_the_ignore_cache_flag() -> Result<()> {
3541 let current_version = "0.1.0";
3542 let target_version = "0.2.0";
3543
3544 let tmp_data_dir = assert_fs::TempDir::new()?;
3545 let current_install_dir = tmp_data_dir.child("antnode_install");
3546 current_install_dir.create_dir_all()?;
3547
3548 let current_node_bin = current_install_dir.child("antnode");
3549 current_node_bin.write_binary(b"fake antnode binary")?;
3550 let target_node_bin = tmp_data_dir.child("antnode");
3551 target_node_bin.write_binary(b"fake antnode binary")?;
3552
3553 let mut mock_service_control = MockServiceControl::new();
3554 let mut mock_rpc_client = MockRpcClient::new();
3555
3556 mock_service_control
3558 .expect_get_process_pid()
3559 .with(eq(current_node_bin.to_path_buf().clone()))
3560 .times(1)
3561 .returning(|_| Ok(1000));
3562 mock_service_control
3563 .expect_stop()
3564 .with(eq("antnode1"), eq(false))
3565 .times(1)
3566 .returning(|_, _| Ok(()));
3567
3568 mock_service_control
3570 .expect_uninstall()
3571 .with(eq("antnode1"), eq(false))
3572 .times(1)
3573 .returning(|_, _| Ok(()));
3574 mock_service_control
3575 .expect_install()
3576 .with(
3577 eq(ServiceInstallCtx {
3578 args: vec![
3579 OsString::from("--rpc"),
3580 OsString::from("127.0.0.1:8081"),
3581 OsString::from("--root-dir"),
3582 OsString::from("/var/antctl/services/antnode1"),
3583 OsString::from("--log-output-dest"),
3584 OsString::from("/var/log/antnode/antnode1"),
3585 OsString::from("--ignore-cache"),
3586 OsString::from("--rewards-address"),
3587 OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"),
3588 OsString::from("evm-arbitrum-one"),
3589 ],
3590 autostart: false,
3591 contents: None,
3592 environment: None,
3593 label: "antnode1".parse()?,
3594 program: current_node_bin.to_path_buf(),
3595 username: Some("ant".to_string()),
3596 working_directory: None,
3597 disable_restart_on_failure: true,
3598 }),
3599 eq(false),
3600 )
3601 .times(1)
3602 .returning(|_, _| Ok(()));
3603
3604 mock_service_control
3606 .expect_start()
3607 .with(eq("antnode1"), eq(false))
3608 .times(1)
3609 .returning(|_, _| Ok(()));
3610 mock_service_control
3611 .expect_wait()
3612 .with(eq(3000))
3613 .times(1)
3614 .returning(|_| ());
3615 mock_service_control
3616 .expect_get_process_pid()
3617 .with(eq(current_node_bin.to_path_buf().clone()))
3618 .times(1)
3619 .returning(|_| Ok(100));
3620
3621 mock_rpc_client.expect_node_info().times(1).returning(|| {
3622 Ok(NodeInfo {
3623 pid: 2000,
3624 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
3625 data_path: PathBuf::from("/var/antctl/services/antnode1"),
3626 log_path: PathBuf::from("/var/log/antnode/antnode1"),
3627 version: target_version.to_string(),
3628 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
3630 })
3631 });
3632 mock_rpc_client
3633 .expect_network_info()
3634 .times(1)
3635 .returning(|| {
3636 Ok(NetworkInfo {
3637 connected_peers: Vec::new(),
3638 listeners: Vec::new(),
3639 })
3640 });
3641
3642 let service_data = NodeServiceData {
3643 alpha: false,
3644 auto_restart: false,
3645 connected_peers: None,
3646 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
3647 evm_network: EvmNetwork::ArbitrumOne,
3648 relay: false,
3649 initial_peers_config: InitialPeersConfig {
3650 first: false,
3651 addrs: vec![],
3652 network_contacts_url: vec![],
3653 local: false,
3654 ignore_cache: true,
3655 bootstrap_cache_dir: None,
3656 },
3657 listen_addr: None,
3658 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
3659 log_format: None,
3660 max_archived_log_files: None,
3661 max_log_files: None,
3662 metrics_port: None,
3663 network_id: None,
3664 node_ip: None,
3665 node_port: None,
3666 number: 1,
3667 peer_id: Some(PeerId::from_str(
3668 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
3669 )?),
3670 pid: Some(1000),
3671 rewards_address: RewardsAddress::from_str(
3672 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
3673 )?,
3674 reward_balance: Some(AttoTokens::zero()),
3675 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
3676 antnode_path: current_node_bin.to_path_buf(),
3677 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
3678 service_name: "antnode1".to_string(),
3679 status: ServiceStatus::Running,
3680 no_upnp: false,
3681 user: Some("ant".to_string()),
3682 user_mode: false,
3683 version: current_version.to_string(),
3684 write_older_cache_files: false,
3685 };
3686 let service_data = Arc::new(RwLock::new(service_data));
3687 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
3688
3689 let mut service_manager = ServiceManager::new(
3690 service,
3691 Box::new(mock_service_control),
3692 VerbosityLevel::Normal,
3693 );
3694
3695 service_manager
3696 .upgrade(UpgradeOptions {
3697 auto_restart: false,
3698 env_variables: None,
3699 force: false,
3700 start_service: true,
3701 target_bin_path: target_node_bin.to_path_buf(),
3702 target_version: Version::parse(target_version).unwrap(),
3703 })
3704 .await?;
3705
3706 let service_data = service_data.read().await;
3707 assert!(service_data.initial_peers_config.ignore_cache);
3708
3709 Ok(())
3710 }
3711
3712 #[tokio::test]
3713 async fn upgrade_should_retain_the_custom_bootstrap_cache_path() -> Result<()> {
3714 let current_version = "0.1.0";
3715 let target_version = "0.2.0";
3716
3717 let tmp_data_dir = assert_fs::TempDir::new()?;
3718 let current_install_dir = tmp_data_dir.child("antnode_install");
3719 current_install_dir.create_dir_all()?;
3720
3721 let current_node_bin = current_install_dir.child("antnode");
3722 current_node_bin.write_binary(b"fake antnode binary")?;
3723 let target_node_bin = tmp_data_dir.child("antnode");
3724 target_node_bin.write_binary(b"fake antnode binary")?;
3725
3726 let mut mock_service_control = MockServiceControl::new();
3727 let mut mock_rpc_client = MockRpcClient::new();
3728
3729 mock_service_control
3731 .expect_get_process_pid()
3732 .with(eq(current_node_bin.to_path_buf().clone()))
3733 .times(1)
3734 .returning(|_| Ok(1000));
3735 mock_service_control
3736 .expect_stop()
3737 .with(eq("antnode1"), eq(false))
3738 .times(1)
3739 .returning(|_, _| Ok(()));
3740
3741 mock_service_control
3743 .expect_uninstall()
3744 .with(eq("antnode1"), eq(false))
3745 .times(1)
3746 .returning(|_, _| Ok(()));
3747 mock_service_control
3748 .expect_install()
3749 .with(
3750 eq(ServiceInstallCtx {
3751 args: vec![
3752 OsString::from("--rpc"),
3753 OsString::from("127.0.0.1:8081"),
3754 OsString::from("--root-dir"),
3755 OsString::from("/var/antctl/services/antnode1"),
3756 OsString::from("--log-output-dest"),
3757 OsString::from("/var/log/antnode/antnode1"),
3758 OsString::from("--bootstrap-cache-dir"),
3759 OsString::from("/var/antctl/services/antnode1/bootstrap_cache"),
3760 OsString::from("--rewards-address"),
3761 OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"),
3762 OsString::from("evm-arbitrum-one"),
3763 ],
3764 autostart: false,
3765 contents: None,
3766 environment: None,
3767 label: "antnode1".parse()?,
3768 program: current_node_bin.to_path_buf(),
3769 username: Some("ant".to_string()),
3770 working_directory: None,
3771 disable_restart_on_failure: true,
3772 }),
3773 eq(false),
3774 )
3775 .times(1)
3776 .returning(|_, _| Ok(()));
3777
3778 mock_service_control
3780 .expect_start()
3781 .with(eq("antnode1"), eq(false))
3782 .times(1)
3783 .returning(|_, _| Ok(()));
3784 mock_service_control
3785 .expect_wait()
3786 .with(eq(3000))
3787 .times(1)
3788 .returning(|_| ());
3789 mock_service_control
3790 .expect_get_process_pid()
3791 .with(eq(current_node_bin.to_path_buf().clone()))
3792 .times(1)
3793 .returning(|_| Ok(100));
3794
3795 mock_rpc_client.expect_node_info().times(1).returning(|| {
3796 Ok(NodeInfo {
3797 pid: 2000,
3798 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
3799 data_path: PathBuf::from("/var/antctl/services/antnode1"),
3800 log_path: PathBuf::from("/var/log/antnode/antnode1"),
3801 version: target_version.to_string(),
3802 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
3804 })
3805 });
3806 mock_rpc_client
3807 .expect_network_info()
3808 .times(1)
3809 .returning(|| {
3810 Ok(NetworkInfo {
3811 connected_peers: Vec::new(),
3812 listeners: Vec::new(),
3813 })
3814 });
3815
3816 let service_data = NodeServiceData {
3817 alpha: false,
3818 auto_restart: false,
3819 connected_peers: None,
3820 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
3821 evm_network: EvmNetwork::ArbitrumOne,
3822 relay: false,
3823 initial_peers_config: InitialPeersConfig {
3824 first: false,
3825 addrs: vec![],
3826 network_contacts_url: vec![],
3827 local: false,
3828 ignore_cache: false,
3829 bootstrap_cache_dir: Some(PathBuf::from(
3830 "/var/antctl/services/antnode1/bootstrap_cache",
3831 )),
3832 },
3833 listen_addr: None,
3834 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
3835 log_format: None,
3836 max_archived_log_files: None,
3837 max_log_files: None,
3838 metrics_port: None,
3839 network_id: None,
3840 node_ip: None,
3841 node_port: None,
3842 number: 1,
3843 peer_id: Some(PeerId::from_str(
3844 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
3845 )?),
3846 pid: Some(1000),
3847 rewards_address: RewardsAddress::from_str(
3848 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
3849 )?,
3850 reward_balance: Some(AttoTokens::zero()),
3851 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
3852 antnode_path: current_node_bin.to_path_buf(),
3853 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
3854 service_name: "antnode1".to_string(),
3855 status: ServiceStatus::Running,
3856 no_upnp: false,
3857 user: Some("ant".to_string()),
3858 user_mode: false,
3859 version: current_version.to_string(),
3860 write_older_cache_files: false,
3861 };
3862 let service_data = Arc::new(RwLock::new(service_data));
3863 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
3864
3865 let mut service_manager = ServiceManager::new(
3866 service,
3867 Box::new(mock_service_control),
3868 VerbosityLevel::Normal,
3869 );
3870
3871 service_manager
3872 .upgrade(UpgradeOptions {
3873 auto_restart: false,
3874 env_variables: None,
3875 force: false,
3876 start_service: true,
3877 target_bin_path: target_node_bin.to_path_buf(),
3878 target_version: Version::parse(target_version).unwrap(),
3879 })
3880 .await?;
3881
3882 let service_data = service_data.read().await;
3883 assert_eq!(
3884 service_data.initial_peers_config.bootstrap_cache_dir,
3885 Some(PathBuf::from(
3886 "/var/antctl/services/antnode1/bootstrap_cache"
3887 ))
3888 );
3889
3890 Ok(())
3891 }
3892
3893 #[tokio::test]
3894 async fn upgrade_should_retain_the_no_upnp_flag() -> Result<()> {
3895 let current_version = "0.1.0";
3896 let target_version = "0.2.0";
3897
3898 let tmp_data_dir = assert_fs::TempDir::new()?;
3899 let current_install_dir = tmp_data_dir.child("antnode_install");
3900 current_install_dir.create_dir_all()?;
3901
3902 let current_node_bin = current_install_dir.child("antnode");
3903 current_node_bin.write_binary(b"fake antnode binary")?;
3904 let target_node_bin = tmp_data_dir.child("antnode");
3905 target_node_bin.write_binary(b"fake antnode binary")?;
3906
3907 let mut mock_service_control = MockServiceControl::new();
3908 let mut mock_rpc_client = MockRpcClient::new();
3909
3910 mock_service_control
3912 .expect_get_process_pid()
3913 .with(eq(current_node_bin.to_path_buf().clone()))
3914 .times(1)
3915 .returning(|_| Ok(1000));
3916 mock_service_control
3917 .expect_stop()
3918 .with(eq("antnode1"), eq(false))
3919 .times(1)
3920 .returning(|_, _| Ok(()));
3921
3922 mock_service_control
3924 .expect_uninstall()
3925 .with(eq("antnode1"), eq(false))
3926 .times(1)
3927 .returning(|_, _| Ok(()));
3928 mock_service_control
3929 .expect_install()
3930 .with(
3931 eq(ServiceInstallCtx {
3932 args: vec![
3933 OsString::from("--rpc"),
3934 OsString::from("127.0.0.1:8081"),
3935 OsString::from("--root-dir"),
3936 OsString::from("/var/antctl/services/antnode1"),
3937 OsString::from("--log-output-dest"),
3938 OsString::from("/var/log/antnode/antnode1"),
3939 OsString::from("--no-upnp"),
3940 OsString::from("--rewards-address"),
3941 OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"),
3942 OsString::from("evm-arbitrum-one"),
3943 ],
3944 autostart: false,
3945 contents: None,
3946 environment: None,
3947 label: "antnode1".parse()?,
3948 program: current_node_bin.to_path_buf(),
3949 username: Some("ant".to_string()),
3950 working_directory: None,
3951 disable_restart_on_failure: true,
3952 }),
3953 eq(false),
3954 )
3955 .times(1)
3956 .returning(|_, _| Ok(()));
3957
3958 mock_service_control
3960 .expect_start()
3961 .with(eq("antnode1"), eq(false))
3962 .times(1)
3963 .returning(|_, _| Ok(()));
3964 mock_service_control
3965 .expect_wait()
3966 .with(eq(3000))
3967 .times(1)
3968 .returning(|_| ());
3969 mock_service_control
3970 .expect_get_process_pid()
3971 .with(eq(current_node_bin.to_path_buf().clone()))
3972 .times(1)
3973 .returning(|_| Ok(100));
3974
3975 mock_rpc_client.expect_node_info().times(1).returning(|| {
3976 Ok(NodeInfo {
3977 pid: 2000,
3978 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
3979 data_path: PathBuf::from("/var/antctl/services/antnode1"),
3980 log_path: PathBuf::from("/var/log/antnode/antnode1"),
3981 version: target_version.to_string(),
3982 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
3984 })
3985 });
3986 mock_rpc_client
3987 .expect_network_info()
3988 .times(1)
3989 .returning(|| {
3990 Ok(NetworkInfo {
3991 connected_peers: Vec::new(),
3992 listeners: Vec::new(),
3993 })
3994 });
3995
3996 let service_data = NodeServiceData {
3997 alpha: false,
3998 auto_restart: false,
3999 connected_peers: None,
4000 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
4001 evm_network: EvmNetwork::ArbitrumOne,
4002 relay: false,
4003 initial_peers_config: Default::default(),
4004 listen_addr: None,
4005 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
4006 log_format: None,
4007 max_archived_log_files: None,
4008 max_log_files: None,
4009 metrics_port: None,
4010 network_id: None,
4011 node_ip: None,
4012 node_port: None,
4013 no_upnp: true,
4014 number: 1,
4015 peer_id: Some(PeerId::from_str(
4016 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
4017 )?),
4018 pid: Some(1000),
4019 rewards_address: RewardsAddress::from_str(
4020 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
4021 )?,
4022 reward_balance: Some(AttoTokens::zero()),
4023 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
4024 antnode_path: current_node_bin.to_path_buf(),
4025 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
4026 service_name: "antnode1".to_string(),
4027 status: ServiceStatus::Running,
4028 user: Some("ant".to_string()),
4029 user_mode: false,
4030 version: current_version.to_string(),
4031 write_older_cache_files: false,
4032 };
4033 let service_data = Arc::new(RwLock::new(service_data));
4034 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
4035
4036 let mut service_manager = ServiceManager::new(
4037 service,
4038 Box::new(mock_service_control),
4039 VerbosityLevel::Normal,
4040 );
4041
4042 service_manager
4043 .upgrade(UpgradeOptions {
4044 auto_restart: false,
4045 env_variables: None,
4046 force: false,
4047 start_service: true,
4048 target_bin_path: target_node_bin.to_path_buf(),
4049 target_version: Version::parse(target_version).unwrap(),
4050 })
4051 .await?;
4052
4053 let service_data = service_data.read().await;
4054 assert!(service_data.no_upnp);
4055
4056 Ok(())
4057 }
4058
4059 #[tokio::test]
4060 async fn upgrade_should_retain_the_log_format_flag() -> Result<()> {
4061 let current_version = "0.1.0";
4062 let target_version = "0.2.0";
4063
4064 let tmp_data_dir = assert_fs::TempDir::new()?;
4065 let current_install_dir = tmp_data_dir.child("antnode_install");
4066 current_install_dir.create_dir_all()?;
4067
4068 let current_node_bin = current_install_dir.child("antnode");
4069 current_node_bin.write_binary(b"fake antnode binary")?;
4070 let target_node_bin = tmp_data_dir.child("antnode");
4071 target_node_bin.write_binary(b"fake antnode binary")?;
4072
4073 let mut mock_service_control = MockServiceControl::new();
4074 let mut mock_rpc_client = MockRpcClient::new();
4075
4076 mock_service_control
4078 .expect_get_process_pid()
4079 .with(eq(current_node_bin.to_path_buf().clone()))
4080 .times(1)
4081 .returning(|_| Ok(1000));
4082 mock_service_control
4083 .expect_stop()
4084 .with(eq("antnode1"), eq(false))
4085 .times(1)
4086 .returning(|_, _| Ok(()));
4087
4088 mock_service_control
4090 .expect_uninstall()
4091 .with(eq("antnode1"), eq(false))
4092 .times(1)
4093 .returning(|_, _| Ok(()));
4094 mock_service_control
4095 .expect_install()
4096 .with(
4097 eq(ServiceInstallCtx {
4098 args: vec![
4099 OsString::from("--rpc"),
4100 OsString::from("127.0.0.1:8081"),
4101 OsString::from("--root-dir"),
4102 OsString::from("/var/antctl/services/antnode1"),
4103 OsString::from("--log-output-dest"),
4104 OsString::from("/var/log/antnode/antnode1"),
4105 OsString::from("--log-format"),
4106 OsString::from("json"),
4107 OsString::from("--rewards-address"),
4108 OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"),
4109 OsString::from("evm-arbitrum-one"),
4110 ],
4111 autostart: false,
4112 contents: None,
4113 environment: None,
4114 label: "antnode1".parse()?,
4115 program: current_node_bin.to_path_buf(),
4116 username: Some("ant".to_string()),
4117 working_directory: None,
4118 disable_restart_on_failure: true,
4119 }),
4120 eq(false),
4121 )
4122 .times(1)
4123 .returning(|_, _| Ok(()));
4124
4125 mock_service_control
4127 .expect_start()
4128 .with(eq("antnode1"), eq(false))
4129 .times(1)
4130 .returning(|_, _| Ok(()));
4131 mock_service_control
4132 .expect_wait()
4133 .with(eq(3000))
4134 .times(1)
4135 .returning(|_| ());
4136 mock_service_control
4137 .expect_get_process_pid()
4138 .with(eq(current_node_bin.to_path_buf().clone()))
4139 .times(1)
4140 .returning(|_| Ok(100));
4141
4142 mock_rpc_client.expect_node_info().times(1).returning(|| {
4143 Ok(NodeInfo {
4144 pid: 2000,
4145 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
4146 data_path: PathBuf::from("/var/antctl/services/antnode1"),
4147 log_path: PathBuf::from("/var/log/antnode/antnode1"),
4148 version: target_version.to_string(),
4149 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
4151 })
4152 });
4153 mock_rpc_client
4154 .expect_network_info()
4155 .times(1)
4156 .returning(|| {
4157 Ok(NetworkInfo {
4158 connected_peers: Vec::new(),
4159 listeners: Vec::new(),
4160 })
4161 });
4162
4163 let service_data = NodeServiceData {
4164 alpha: false,
4165 auto_restart: false,
4166 connected_peers: None,
4167 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
4168 evm_network: EvmNetwork::ArbitrumOne,
4169 relay: false,
4170 initial_peers_config: Default::default(),
4171 listen_addr: None,
4172 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
4173 log_format: Some(LogFormat::Json),
4174 max_archived_log_files: None,
4175 max_log_files: None,
4176 metrics_port: None,
4177 network_id: None,
4178 node_ip: None,
4179 node_port: None,
4180 number: 1,
4181 peer_id: Some(PeerId::from_str(
4182 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
4183 )?),
4184 pid: Some(1000),
4185 rewards_address: RewardsAddress::from_str(
4186 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
4187 )?,
4188 reward_balance: Some(AttoTokens::zero()),
4189 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
4190 antnode_path: current_node_bin.to_path_buf(),
4191 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
4192 service_name: "antnode1".to_string(),
4193 status: ServiceStatus::Running,
4194 no_upnp: false,
4195 user: Some("ant".to_string()),
4196 user_mode: false,
4197 version: current_version.to_string(),
4198 write_older_cache_files: false,
4199 };
4200 let service_data = Arc::new(RwLock::new(service_data));
4201 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
4202
4203 let mut service_manager = ServiceManager::new(
4204 service,
4205 Box::new(mock_service_control),
4206 VerbosityLevel::Normal,
4207 );
4208
4209 service_manager
4210 .upgrade(UpgradeOptions {
4211 auto_restart: false,
4212 env_variables: None,
4213 force: false,
4214 start_service: true,
4215 target_bin_path: target_node_bin.to_path_buf(),
4216 target_version: Version::parse(target_version).unwrap(),
4217 })
4218 .await?;
4219
4220 let service_data = service_data.read().await;
4221 assert!(service_data.log_format.is_some());
4222 assert_eq!(service_data.log_format, Some(LogFormat::Json));
4223
4224 Ok(())
4225 }
4226
4227 #[tokio::test]
4228 async fn upgrade_should_retain_the_relay_flag() -> Result<()> {
4229 let current_version = "0.1.0";
4230 let target_version = "0.2.0";
4231
4232 let tmp_data_dir = assert_fs::TempDir::new()?;
4233 let current_install_dir = tmp_data_dir.child("antnode_install");
4234 current_install_dir.create_dir_all()?;
4235
4236 let current_node_bin = current_install_dir.child("antnode");
4237 current_node_bin.write_binary(b"fake antnode binary")?;
4238 let target_node_bin = tmp_data_dir.child("antnode");
4239 target_node_bin.write_binary(b"fake antnode binary")?;
4240
4241 let mut mock_service_control = MockServiceControl::new();
4242 let mut mock_rpc_client = MockRpcClient::new();
4243
4244 mock_service_control
4246 .expect_get_process_pid()
4247 .with(eq(current_node_bin.to_path_buf().clone()))
4248 .times(1)
4249 .returning(|_| Ok(1000));
4250 mock_service_control
4251 .expect_stop()
4252 .with(eq("antnode1"), eq(false))
4253 .times(1)
4254 .returning(|_, _| Ok(()));
4255
4256 mock_service_control
4258 .expect_uninstall()
4259 .with(eq("antnode1"), eq(false))
4260 .times(1)
4261 .returning(|_, _| Ok(()));
4262 mock_service_control
4263 .expect_install()
4264 .with(
4265 eq(ServiceInstallCtx {
4266 args: vec![
4267 OsString::from("--rpc"),
4268 OsString::from("127.0.0.1:8081"),
4269 OsString::from("--root-dir"),
4270 OsString::from("/var/antctl/services/antnode1"),
4271 OsString::from("--log-output-dest"),
4272 OsString::from("/var/log/antnode/antnode1"),
4273 OsString::from("--relay"),
4274 OsString::from("--rewards-address"),
4275 OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"),
4276 OsString::from("evm-arbitrum-one"),
4277 ],
4278 autostart: false,
4279 contents: None,
4280 environment: None,
4281 label: "antnode1".parse()?,
4282 program: current_node_bin.to_path_buf(),
4283 username: Some("ant".to_string()),
4284 working_directory: None,
4285 disable_restart_on_failure: true,
4286 }),
4287 eq(false),
4288 )
4289 .times(1)
4290 .returning(|_, _| Ok(()));
4291
4292 mock_service_control
4294 .expect_start()
4295 .with(eq("antnode1"), eq(false))
4296 .times(1)
4297 .returning(|_, _| Ok(()));
4298 mock_service_control
4299 .expect_wait()
4300 .with(eq(3000))
4301 .times(1)
4302 .returning(|_| ());
4303 mock_service_control
4304 .expect_get_process_pid()
4305 .with(eq(current_node_bin.to_path_buf().clone()))
4306 .times(1)
4307 .returning(|_| Ok(100));
4308
4309 mock_rpc_client.expect_node_info().times(1).returning(|| {
4310 Ok(NodeInfo {
4311 pid: 2000,
4312 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
4313 data_path: PathBuf::from("/var/antctl/services/antnode1"),
4314 log_path: PathBuf::from("/var/log/antnode/antnode1"),
4315 version: target_version.to_string(),
4316 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
4318 })
4319 });
4320 mock_rpc_client
4321 .expect_network_info()
4322 .times(1)
4323 .returning(|| {
4324 Ok(NetworkInfo {
4325 connected_peers: Vec::new(),
4326 listeners: Vec::new(),
4327 })
4328 });
4329
4330 let service_data = NodeServiceData {
4331 alpha: false,
4332 auto_restart: false,
4333 connected_peers: None,
4334 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
4335 evm_network: EvmNetwork::ArbitrumOne,
4336 relay: true,
4337 initial_peers_config: Default::default(),
4338 listen_addr: None,
4339 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
4340 log_format: None,
4341 max_archived_log_files: None,
4342 max_log_files: None,
4343 metrics_port: None,
4344 network_id: None,
4345 node_ip: None,
4346 node_port: None,
4347 number: 1,
4348 peer_id: Some(PeerId::from_str(
4349 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
4350 )?),
4351 pid: Some(1000),
4352 rewards_address: RewardsAddress::from_str(
4353 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
4354 )?,
4355 reward_balance: Some(AttoTokens::zero()),
4356 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
4357 antnode_path: current_node_bin.to_path_buf(),
4358 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
4359 service_name: "antnode1".to_string(),
4360 status: ServiceStatus::Running,
4361 no_upnp: false,
4362 user: Some("ant".to_string()),
4363 user_mode: false,
4364 version: current_version.to_string(),
4365 write_older_cache_files: false,
4366 };
4367 let service_data = Arc::new(RwLock::new(service_data));
4368 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
4369
4370 let mut service_manager = ServiceManager::new(
4371 service,
4372 Box::new(mock_service_control),
4373 VerbosityLevel::Normal,
4374 );
4375
4376 service_manager
4377 .upgrade(UpgradeOptions {
4378 auto_restart: false,
4379 env_variables: None,
4380 force: false,
4381 start_service: true,
4382 target_bin_path: target_node_bin.to_path_buf(),
4383 target_version: Version::parse(target_version).unwrap(),
4384 })
4385 .await?;
4386
4387 let service_data = service_data.read().await;
4388 assert!(service_data.relay);
4389
4390 Ok(())
4391 }
4392
4393 #[tokio::test]
4394 async fn upgrade_should_retain_custom_node_ip() -> Result<()> {
4395 let current_version = "0.1.0";
4396 let target_version = "0.2.0";
4397
4398 let tmp_data_dir = assert_fs::TempDir::new()?;
4399 let current_install_dir = tmp_data_dir.child("antnode_install");
4400 current_install_dir.create_dir_all()?;
4401
4402 let current_node_bin = current_install_dir.child("antnode");
4403 current_node_bin.write_binary(b"fake antnode binary")?;
4404 let target_node_bin = tmp_data_dir.child("antnode");
4405 target_node_bin.write_binary(b"fake antnode binary")?;
4406
4407 let mut mock_service_control = MockServiceControl::new();
4408 let mut mock_rpc_client = MockRpcClient::new();
4409
4410 mock_service_control
4412 .expect_get_process_pid()
4413 .with(eq(current_node_bin.to_path_buf().clone()))
4414 .times(1)
4415 .returning(|_| Ok(1000));
4416 mock_service_control
4417 .expect_stop()
4418 .with(eq("antnode1"), eq(false))
4419 .times(1)
4420 .returning(|_, _| Ok(()));
4421
4422 mock_service_control
4424 .expect_uninstall()
4425 .with(eq("antnode1"), eq(false))
4426 .times(1)
4427 .returning(|_, _| Ok(()));
4428 mock_service_control
4429 .expect_install()
4430 .with(
4431 eq(ServiceInstallCtx {
4432 args: vec![
4433 OsString::from("--rpc"),
4434 OsString::from("127.0.0.1:8081"),
4435 OsString::from("--root-dir"),
4436 OsString::from("/var/antctl/services/antnode1"),
4437 OsString::from("--log-output-dest"),
4438 OsString::from("/var/log/antnode/antnode1"),
4439 OsString::from("--ip"),
4440 OsString::from("192.168.1.1"),
4441 OsString::from("--rewards-address"),
4442 OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"),
4443 OsString::from("evm-arbitrum-one"),
4444 ],
4445 autostart: false,
4446 contents: None,
4447 environment: None,
4448 label: "antnode1".parse()?,
4449 program: current_node_bin.to_path_buf(),
4450 username: Some("ant".to_string()),
4451 working_directory: None,
4452 disable_restart_on_failure: true,
4453 }),
4454 eq(false),
4455 )
4456 .times(1)
4457 .returning(|_, _| Ok(()));
4458
4459 mock_service_control
4461 .expect_start()
4462 .with(eq("antnode1"), eq(false))
4463 .times(1)
4464 .returning(|_, _| Ok(()));
4465 mock_service_control
4466 .expect_wait()
4467 .with(eq(3000))
4468 .times(1)
4469 .returning(|_| ());
4470 mock_service_control
4471 .expect_get_process_pid()
4472 .with(eq(current_node_bin.to_path_buf().clone()))
4473 .times(1)
4474 .returning(|_| Ok(100));
4475
4476 mock_rpc_client.expect_node_info().times(1).returning(|| {
4477 Ok(NodeInfo {
4478 pid: 2000,
4479 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
4480 data_path: PathBuf::from("/var/antctl/services/antnode1"),
4481 log_path: PathBuf::from("/var/log/antnode/antnode1"),
4482 version: target_version.to_string(),
4483 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
4485 })
4486 });
4487 mock_rpc_client
4488 .expect_network_info()
4489 .times(1)
4490 .returning(|| {
4491 Ok(NetworkInfo {
4492 connected_peers: Vec::new(),
4493 listeners: Vec::new(),
4494 })
4495 });
4496
4497 let service_data = NodeServiceData {
4498 alpha: false,
4499 auto_restart: false,
4500 connected_peers: None,
4501 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
4502 evm_network: EvmNetwork::ArbitrumOne,
4503 relay: false,
4504 initial_peers_config: Default::default(),
4505 listen_addr: None,
4506 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
4507 log_format: None,
4508 max_archived_log_files: None,
4509 max_log_files: None,
4510 metrics_port: None,
4511 network_id: None,
4512 number: 1,
4513 node_ip: Some(Ipv4Addr::new(192, 168, 1, 1)),
4514 node_port: None,
4515 peer_id: Some(PeerId::from_str(
4516 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
4517 )?),
4518 pid: Some(1000),
4519 rewards_address: RewardsAddress::from_str(
4520 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
4521 )?,
4522 reward_balance: Some(AttoTokens::zero()),
4523 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
4524 antnode_path: current_node_bin.to_path_buf(),
4525 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
4526 service_name: "antnode1".to_string(),
4527 status: ServiceStatus::Running,
4528 no_upnp: false,
4529 user: Some("ant".to_string()),
4530 user_mode: false,
4531 version: current_version.to_string(),
4532 write_older_cache_files: false,
4533 };
4534 let service_data = Arc::new(RwLock::new(service_data));
4535 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
4536
4537 let mut service_manager = ServiceManager::new(
4538 service,
4539 Box::new(mock_service_control),
4540 VerbosityLevel::Normal,
4541 );
4542
4543 service_manager
4544 .upgrade(UpgradeOptions {
4545 auto_restart: false,
4546 env_variables: None,
4547 force: false,
4548 start_service: true,
4549 target_bin_path: target_node_bin.to_path_buf(),
4550 target_version: Version::parse(target_version).unwrap(),
4551 })
4552 .await?;
4553
4554 let service_data = service_data.read().await;
4555 assert_eq!(service_data.node_ip, Some(Ipv4Addr::new(192, 168, 1, 1)));
4556
4557 Ok(())
4558 }
4559
4560 #[tokio::test]
4561 async fn upgrade_should_retain_custom_node_ports() -> Result<()> {
4562 let current_version = "0.1.0";
4563 let target_version = "0.2.0";
4564
4565 let tmp_data_dir = assert_fs::TempDir::new()?;
4566 let current_install_dir = tmp_data_dir.child("antnode_install");
4567 current_install_dir.create_dir_all()?;
4568
4569 let current_node_bin = current_install_dir.child("antnode");
4570 current_node_bin.write_binary(b"fake antnode binary")?;
4571 let target_node_bin = tmp_data_dir.child("antnode");
4572 target_node_bin.write_binary(b"fake antnode binary")?;
4573
4574 let mut mock_service_control = MockServiceControl::new();
4575 let mut mock_rpc_client = MockRpcClient::new();
4576
4577 mock_service_control
4579 .expect_get_process_pid()
4580 .with(eq(current_node_bin.to_path_buf().clone()))
4581 .times(1)
4582 .returning(|_| Ok(1000));
4583 mock_service_control
4584 .expect_stop()
4585 .with(eq("antnode1"), eq(false))
4586 .times(1)
4587 .returning(|_, _| Ok(()));
4588
4589 mock_service_control
4591 .expect_uninstall()
4592 .with(eq("antnode1"), eq(false))
4593 .times(1)
4594 .returning(|_, _| Ok(()));
4595 mock_service_control
4596 .expect_install()
4597 .with(
4598 eq(ServiceInstallCtx {
4599 args: vec![
4600 OsString::from("--rpc"),
4601 OsString::from("127.0.0.1:8081"),
4602 OsString::from("--root-dir"),
4603 OsString::from("/var/antctl/services/antnode1"),
4604 OsString::from("--log-output-dest"),
4605 OsString::from("/var/log/antnode/antnode1"),
4606 OsString::from("--port"),
4607 OsString::from("12000"),
4608 OsString::from("--rewards-address"),
4609 OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"),
4610 OsString::from("evm-arbitrum-one"),
4611 ],
4612 autostart: false,
4613 contents: None,
4614 environment: None,
4615 label: "antnode1".parse()?,
4616 program: current_node_bin.to_path_buf(),
4617 username: Some("ant".to_string()),
4618 working_directory: None,
4619 disable_restart_on_failure: true,
4620 }),
4621 eq(false),
4622 )
4623 .times(1)
4624 .returning(|_, _| Ok(()));
4625
4626 mock_service_control
4628 .expect_start()
4629 .with(eq("antnode1"), eq(false))
4630 .times(1)
4631 .returning(|_, _| Ok(()));
4632 mock_service_control
4633 .expect_wait()
4634 .with(eq(3000))
4635 .times(1)
4636 .returning(|_| ());
4637 mock_service_control
4638 .expect_get_process_pid()
4639 .with(eq(current_node_bin.to_path_buf().clone()))
4640 .times(1)
4641 .returning(|_| Ok(100));
4642
4643 mock_rpc_client.expect_node_info().times(1).returning(|| {
4644 Ok(NodeInfo {
4645 pid: 2000,
4646 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
4647 data_path: PathBuf::from("/var/antctl/services/antnode1"),
4648 log_path: PathBuf::from("/var/log/antnode/antnode1"),
4649 version: target_version.to_string(),
4650 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
4652 })
4653 });
4654 mock_rpc_client
4655 .expect_network_info()
4656 .times(1)
4657 .returning(|| {
4658 Ok(NetworkInfo {
4659 connected_peers: Vec::new(),
4660 listeners: Vec::new(),
4661 })
4662 });
4663
4664 let service_data = NodeServiceData {
4665 alpha: false,
4666 auto_restart: false,
4667 connected_peers: None,
4668 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
4669 evm_network: EvmNetwork::ArbitrumOne,
4670 relay: false,
4671 initial_peers_config: Default::default(),
4672 listen_addr: None,
4673 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
4674 log_format: None,
4675 max_archived_log_files: None,
4676 max_log_files: None,
4677 metrics_port: None,
4678 network_id: None,
4679 number: 1,
4680 node_ip: None,
4681 node_port: Some(12000),
4682 peer_id: Some(PeerId::from_str(
4683 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
4684 )?),
4685 pid: Some(1000),
4686 rewards_address: RewardsAddress::from_str(
4687 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
4688 )?,
4689 reward_balance: Some(AttoTokens::zero()),
4690 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
4691 antnode_path: current_node_bin.to_path_buf(),
4692 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
4693 service_name: "antnode1".to_string(),
4694 status: ServiceStatus::Running,
4695 no_upnp: false,
4696 user: Some("ant".to_string()),
4697 user_mode: false,
4698 version: current_version.to_string(),
4699 write_older_cache_files: false,
4700 };
4701 let service_data = Arc::new(RwLock::new(service_data));
4702 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
4703
4704 let mut service_manager = ServiceManager::new(
4705 service,
4706 Box::new(mock_service_control),
4707 VerbosityLevel::Normal,
4708 );
4709
4710 service_manager
4711 .upgrade(UpgradeOptions {
4712 auto_restart: false,
4713 env_variables: None,
4714 force: false,
4715 start_service: true,
4716 target_bin_path: target_node_bin.to_path_buf(),
4717 target_version: Version::parse(target_version).unwrap(),
4718 })
4719 .await?;
4720
4721 let service_data = service_data.read().await;
4722 assert_eq!(service_data.node_port, Some(12000));
4723
4724 Ok(())
4725 }
4726
4727 #[tokio::test]
4728 async fn upgrade_should_retain_max_archived_log_files() -> Result<()> {
4729 let current_version = "0.1.0";
4730 let target_version = "0.2.0";
4731
4732 let tmp_data_dir = assert_fs::TempDir::new()?;
4733 let current_install_dir = tmp_data_dir.child("antnode_install");
4734 current_install_dir.create_dir_all()?;
4735
4736 let current_node_bin = current_install_dir.child("antnode");
4737 current_node_bin.write_binary(b"fake antnode binary")?;
4738 let target_node_bin = tmp_data_dir.child("antnode");
4739 target_node_bin.write_binary(b"fake antnode binary")?;
4740
4741 let mut mock_service_control = MockServiceControl::new();
4742 let mut mock_rpc_client = MockRpcClient::new();
4743
4744 mock_service_control
4746 .expect_get_process_pid()
4747 .with(eq(current_node_bin.to_path_buf().clone()))
4748 .times(1)
4749 .returning(|_| Ok(1000));
4750 mock_service_control
4751 .expect_stop()
4752 .with(eq("antnode1"), eq(false))
4753 .times(1)
4754 .returning(|_, _| Ok(()));
4755
4756 mock_service_control
4758 .expect_uninstall()
4759 .with(eq("antnode1"), eq(false))
4760 .times(1)
4761 .returning(|_, _| Ok(()));
4762 mock_service_control
4763 .expect_install()
4764 .with(
4765 eq(ServiceInstallCtx {
4766 args: vec![
4767 OsString::from("--rpc"),
4768 OsString::from("127.0.0.1:8081"),
4769 OsString::from("--root-dir"),
4770 OsString::from("/var/antctl/services/antnode1"),
4771 OsString::from("--log-output-dest"),
4772 OsString::from("/var/log/antnode/antnode1"),
4773 OsString::from("--max-archived-log-files"),
4774 OsString::from("20"),
4775 OsString::from("--rewards-address"),
4776 OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"),
4777 OsString::from("evm-arbitrum-one"),
4778 ],
4779 autostart: false,
4780 contents: None,
4781 environment: None,
4782 label: "antnode1".parse()?,
4783 program: current_node_bin.to_path_buf(),
4784 username: Some("ant".to_string()),
4785 working_directory: None,
4786 disable_restart_on_failure: true,
4787 }),
4788 eq(false),
4789 )
4790 .times(1)
4791 .returning(|_, _| Ok(()));
4792
4793 mock_service_control
4795 .expect_start()
4796 .with(eq("antnode1"), eq(false))
4797 .times(1)
4798 .returning(|_, _| Ok(()));
4799 mock_service_control
4800 .expect_wait()
4801 .with(eq(3000))
4802 .times(1)
4803 .returning(|_| ());
4804 mock_service_control
4805 .expect_get_process_pid()
4806 .with(eq(current_node_bin.to_path_buf().clone()))
4807 .times(1)
4808 .returning(|_| Ok(100));
4809
4810 mock_rpc_client.expect_node_info().times(1).returning(|| {
4811 Ok(NodeInfo {
4812 pid: 2000,
4813 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
4814 data_path: PathBuf::from("/var/antctl/services/antnode1"),
4815 log_path: PathBuf::from("/var/log/antnode/antnode1"),
4816 version: target_version.to_string(),
4817 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
4819 })
4820 });
4821 mock_rpc_client
4822 .expect_network_info()
4823 .times(1)
4824 .returning(|| {
4825 Ok(NetworkInfo {
4826 connected_peers: Vec::new(),
4827 listeners: Vec::new(),
4828 })
4829 });
4830
4831 let service_data = NodeServiceData {
4832 alpha: false,
4833 auto_restart: false,
4834 connected_peers: None,
4835 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
4836 relay: false,
4837 initial_peers_config: Default::default(),
4838 listen_addr: None,
4839 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
4840 log_format: None,
4841 max_archived_log_files: Some(20),
4842 max_log_files: None,
4843 metrics_port: None,
4844 network_id: None,
4845 node_ip: None,
4846 node_port: None,
4847 number: 1,
4848 peer_id: Some(PeerId::from_str(
4849 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
4850 )?),
4851 pid: Some(1000),
4852 reward_balance: Some(AttoTokens::zero()),
4853 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
4854 antnode_path: current_node_bin.to_path_buf(),
4855 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
4856 service_name: "antnode1".to_string(),
4857 status: ServiceStatus::Running,
4858 no_upnp: false,
4859 user: Some("ant".to_string()),
4860 user_mode: false,
4861 version: current_version.to_string(),
4862 evm_network: EvmNetwork::ArbitrumOne,
4863 rewards_address: RewardsAddress::from_str(
4864 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
4865 )?,
4866 write_older_cache_files: false,
4867 };
4868 let service_data = Arc::new(RwLock::new(service_data));
4869 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
4870
4871 let mut service_manager = ServiceManager::new(
4872 service,
4873 Box::new(mock_service_control),
4874 VerbosityLevel::Normal,
4875 );
4876
4877 service_manager
4878 .upgrade(UpgradeOptions {
4879 auto_restart: false,
4880 env_variables: None,
4881 force: false,
4882 start_service: true,
4883 target_bin_path: target_node_bin.to_path_buf(),
4884 target_version: Version::parse(target_version).unwrap(),
4885 })
4886 .await?;
4887
4888 let service_data = service_data.read().await;
4889 assert_matches!(service_data.max_archived_log_files, Some(20));
4890
4891 Ok(())
4892 }
4893
4894 #[tokio::test]
4895 async fn upgrade_should_retain_max_log_files() -> Result<()> {
4896 let current_version = "0.1.0";
4897 let target_version = "0.2.0";
4898
4899 let tmp_data_dir = assert_fs::TempDir::new()?;
4900 let current_install_dir = tmp_data_dir.child("antnode_install");
4901 current_install_dir.create_dir_all()?;
4902
4903 let current_node_bin = current_install_dir.child("antnode");
4904 current_node_bin.write_binary(b"fake antnode binary")?;
4905 let target_node_bin = tmp_data_dir.child("antnode");
4906 target_node_bin.write_binary(b"fake antnode binary")?;
4907
4908 let mut mock_service_control = MockServiceControl::new();
4909 let mut mock_rpc_client = MockRpcClient::new();
4910
4911 mock_service_control
4913 .expect_get_process_pid()
4914 .with(eq(current_node_bin.to_path_buf().clone()))
4915 .times(1)
4916 .returning(|_| Ok(1000));
4917 mock_service_control
4918 .expect_stop()
4919 .with(eq("antnode1"), eq(false))
4920 .times(1)
4921 .returning(|_, _| Ok(()));
4922
4923 mock_service_control
4925 .expect_uninstall()
4926 .with(eq("antnode1"), eq(false))
4927 .times(1)
4928 .returning(|_, _| Ok(()));
4929 mock_service_control
4930 .expect_install()
4931 .with(
4932 eq(ServiceInstallCtx {
4933 args: vec![
4934 OsString::from("--rpc"),
4935 OsString::from("127.0.0.1:8081"),
4936 OsString::from("--root-dir"),
4937 OsString::from("/var/antctl/services/antnode1"),
4938 OsString::from("--log-output-dest"),
4939 OsString::from("/var/log/antnode/antnode1"),
4940 OsString::from("--max-log-files"),
4941 OsString::from("20"),
4942 OsString::from("--rewards-address"),
4943 OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"),
4944 OsString::from("evm-arbitrum-one"),
4945 ],
4946 autostart: false,
4947 contents: None,
4948 environment: None,
4949 label: "antnode1".parse()?,
4950 program: current_node_bin.to_path_buf(),
4951 username: Some("ant".to_string()),
4952 working_directory: None,
4953 disable_restart_on_failure: true,
4954 }),
4955 eq(false),
4956 )
4957 .times(1)
4958 .returning(|_, _| Ok(()));
4959
4960 mock_service_control
4962 .expect_start()
4963 .with(eq("antnode1"), eq(false))
4964 .times(1)
4965 .returning(|_, _| Ok(()));
4966 mock_service_control
4967 .expect_wait()
4968 .with(eq(3000))
4969 .times(1)
4970 .returning(|_| ());
4971 mock_service_control
4972 .expect_get_process_pid()
4973 .with(eq(current_node_bin.to_path_buf().clone()))
4974 .times(1)
4975 .returning(|_| Ok(100));
4976
4977 mock_rpc_client.expect_node_info().times(1).returning(|| {
4978 Ok(NodeInfo {
4979 pid: 2000,
4980 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
4981 data_path: PathBuf::from("/var/antctl/services/antnode1"),
4982 log_path: PathBuf::from("/var/log/antnode/antnode1"),
4983 version: target_version.to_string(),
4984 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
4986 })
4987 });
4988 mock_rpc_client
4989 .expect_network_info()
4990 .times(1)
4991 .returning(|| {
4992 Ok(NetworkInfo {
4993 connected_peers: Vec::new(),
4994 listeners: Vec::new(),
4995 })
4996 });
4997
4998 let service_data = NodeServiceData {
4999 alpha: false,
5000 auto_restart: false,
5001 connected_peers: None,
5002 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
5003 relay: false,
5004 initial_peers_config: Default::default(),
5005 listen_addr: None,
5006 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
5007 log_format: None,
5008 max_archived_log_files: None,
5009 max_log_files: Some(20),
5010 metrics_port: None,
5011 network_id: None,
5012 node_ip: None,
5013 node_port: None,
5014 number: 1,
5015 peer_id: Some(PeerId::from_str(
5016 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
5017 )?),
5018 pid: Some(1000),
5019 reward_balance: Some(AttoTokens::zero()),
5020 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
5021 antnode_path: current_node_bin.to_path_buf(),
5022 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
5023 service_name: "antnode1".to_string(),
5024 status: ServiceStatus::Running,
5025 no_upnp: false,
5026 user: Some("ant".to_string()),
5027 user_mode: false,
5028 version: current_version.to_string(),
5029 evm_network: EvmNetwork::ArbitrumOne,
5030 rewards_address: RewardsAddress::from_str(
5031 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
5032 )?,
5033 write_older_cache_files: false,
5034 };
5035 let service_data = Arc::new(RwLock::new(service_data));
5036 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
5037
5038 let mut service_manager = ServiceManager::new(
5039 service,
5040 Box::new(mock_service_control),
5041 VerbosityLevel::Normal,
5042 );
5043
5044 service_manager
5045 .upgrade(UpgradeOptions {
5046 auto_restart: false,
5047 env_variables: None,
5048 force: false,
5049 start_service: true,
5050 target_bin_path: target_node_bin.to_path_buf(),
5051 target_version: Version::parse(target_version).unwrap(),
5052 })
5053 .await?;
5054
5055 let service_data = service_data.read().await;
5056 assert_matches!(service_data.max_log_files, Some(20));
5057
5058 Ok(())
5059 }
5060
5061 #[tokio::test]
5062 async fn upgrade_should_retain_custom_metrics_ports() -> Result<()> {
5063 let current_version = "0.1.0";
5064 let target_version = "0.2.0";
5065
5066 let tmp_data_dir = assert_fs::TempDir::new()?;
5067 let current_install_dir = tmp_data_dir.child("antnode_install");
5068 current_install_dir.create_dir_all()?;
5069
5070 let current_node_bin = current_install_dir.child("antnode");
5071 current_node_bin.write_binary(b"fake antnode binary")?;
5072 let target_node_bin = tmp_data_dir.child("antnode");
5073 target_node_bin.write_binary(b"fake antnode binary")?;
5074
5075 let mut mock_service_control = MockServiceControl::new();
5076 let mut mock_rpc_client = MockRpcClient::new();
5077
5078 mock_service_control
5080 .expect_get_process_pid()
5081 .with(eq(current_node_bin.to_path_buf().clone()))
5082 .times(1)
5083 .returning(|_| Ok(1000));
5084 mock_service_control
5085 .expect_stop()
5086 .with(eq("antnode1"), eq(false))
5087 .times(1)
5088 .returning(|_, _| Ok(()));
5089
5090 mock_service_control
5092 .expect_uninstall()
5093 .with(eq("antnode1"), eq(false))
5094 .times(1)
5095 .returning(|_, _| Ok(()));
5096 mock_service_control
5097 .expect_install()
5098 .with(
5099 eq(ServiceInstallCtx {
5100 args: vec![
5101 OsString::from("--rpc"),
5102 OsString::from("127.0.0.1:8081"),
5103 OsString::from("--root-dir"),
5104 OsString::from("/var/antctl/services/antnode1"),
5105 OsString::from("--log-output-dest"),
5106 OsString::from("/var/log/antnode/antnode1"),
5107 OsString::from("--metrics-server-port"),
5108 OsString::from("12000"),
5109 OsString::from("--rewards-address"),
5110 OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"),
5111 OsString::from("evm-arbitrum-one"),
5112 ],
5113 autostart: false,
5114 contents: None,
5115 environment: None,
5116 label: "antnode1".parse()?,
5117 program: current_node_bin.to_path_buf(),
5118 username: Some("ant".to_string()),
5119 working_directory: None,
5120 disable_restart_on_failure: true,
5121 }),
5122 eq(false),
5123 )
5124 .times(1)
5125 .returning(|_, _| Ok(()));
5126
5127 mock_service_control
5129 .expect_start()
5130 .with(eq("antnode1"), eq(false))
5131 .times(1)
5132 .returning(|_, _| Ok(()));
5133 mock_service_control
5134 .expect_wait()
5135 .with(eq(3000))
5136 .times(1)
5137 .returning(|_| ());
5138 mock_service_control
5139 .expect_get_process_pid()
5140 .with(eq(current_node_bin.to_path_buf().clone()))
5141 .times(1)
5142 .returning(|_| Ok(100));
5143
5144 mock_rpc_client.expect_node_info().times(1).returning(|| {
5145 Ok(NodeInfo {
5146 pid: 2000,
5147 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
5148 data_path: PathBuf::from("/var/antctl/services/antnode1"),
5149 log_path: PathBuf::from("/var/log/antnode/antnode1"),
5150 version: target_version.to_string(),
5151 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
5153 })
5154 });
5155 mock_rpc_client
5156 .expect_network_info()
5157 .times(1)
5158 .returning(|| {
5159 Ok(NetworkInfo {
5160 connected_peers: Vec::new(),
5161 listeners: Vec::new(),
5162 })
5163 });
5164
5165 let service_data = NodeServiceData {
5166 alpha: false,
5167 auto_restart: false,
5168 connected_peers: None,
5169 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
5170 evm_network: EvmNetwork::ArbitrumOne,
5171 relay: false,
5172 initial_peers_config: Default::default(),
5173 listen_addr: None,
5174 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
5175 log_format: None,
5176 max_archived_log_files: None,
5177 max_log_files: None,
5178 metrics_port: Some(12000),
5179 network_id: None,
5180 node_ip: None,
5181 node_port: None,
5182 number: 1,
5183 peer_id: Some(PeerId::from_str(
5184 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
5185 )?),
5186 pid: Some(1000),
5187 rewards_address: RewardsAddress::from_str(
5188 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
5189 )?,
5190 reward_balance: Some(AttoTokens::zero()),
5191 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
5192 antnode_path: current_node_bin.to_path_buf(),
5193 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
5194 service_name: "antnode1".to_string(),
5195 status: ServiceStatus::Running,
5196 no_upnp: false,
5197 user: Some("ant".to_string()),
5198 user_mode: false,
5199 version: current_version.to_string(),
5200 write_older_cache_files: false,
5201 };
5202 let service_data = Arc::new(RwLock::new(service_data));
5203 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
5204
5205 let mut service_manager = ServiceManager::new(
5206 service,
5207 Box::new(mock_service_control),
5208 VerbosityLevel::Normal,
5209 );
5210
5211 service_manager
5212 .upgrade(UpgradeOptions {
5213 auto_restart: false,
5214 env_variables: None,
5215 force: false,
5216 start_service: true,
5217 target_bin_path: target_node_bin.to_path_buf(),
5218 target_version: Version::parse(target_version).unwrap(),
5219 })
5220 .await?;
5221
5222 let service_data = service_data.read().await;
5223 assert_eq!(service_data.metrics_port, Some(12000));
5224
5225 Ok(())
5226 }
5227
5228 #[tokio::test]
5229 async fn upgrade_should_retain_custom_rpc_ports() -> Result<()> {
5230 let current_version = "0.1.0";
5231 let target_version = "0.2.0";
5232
5233 let tmp_data_dir = assert_fs::TempDir::new()?;
5234 let current_install_dir = tmp_data_dir.child("antnode_install");
5235 current_install_dir.create_dir_all()?;
5236
5237 let current_node_bin = current_install_dir.child("antnode");
5238 current_node_bin.write_binary(b"fake antnode binary")?;
5239 let target_node_bin = tmp_data_dir.child("antnode");
5240 target_node_bin.write_binary(b"fake antnode binary")?;
5241
5242 let mut mock_service_control = MockServiceControl::new();
5243 let mut mock_rpc_client = MockRpcClient::new();
5244
5245 mock_service_control
5247 .expect_get_process_pid()
5248 .with(eq(current_node_bin.to_path_buf().clone()))
5249 .times(1)
5250 .returning(|_| Ok(1000));
5251 mock_service_control
5252 .expect_stop()
5253 .with(eq("antnode1"), eq(false))
5254 .times(1)
5255 .returning(|_, _| Ok(()));
5256
5257 mock_service_control
5259 .expect_uninstall()
5260 .with(eq("antnode1"), eq(false))
5261 .times(1)
5262 .returning(|_, _| Ok(()));
5263 mock_service_control
5264 .expect_install()
5265 .with(
5266 eq(ServiceInstallCtx {
5267 args: vec![
5268 OsString::from("--rpc"),
5269 OsString::from("127.0.0.1:8081"),
5270 OsString::from("--root-dir"),
5271 OsString::from("/var/antctl/services/antnode1"),
5272 OsString::from("--log-output-dest"),
5273 OsString::from("/var/log/antnode/antnode1"),
5274 OsString::from("--metrics-server-port"),
5275 OsString::from("12000"),
5276 OsString::from("--rewards-address"),
5277 OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"),
5278 OsString::from("evm-arbitrum-one"),
5279 ],
5280 autostart: false,
5281 contents: None,
5282 environment: None,
5283 label: "antnode1".parse()?,
5284 program: current_node_bin.to_path_buf(),
5285 username: Some("ant".to_string()),
5286 working_directory: None,
5287 disable_restart_on_failure: true,
5288 }),
5289 eq(false),
5290 )
5291 .times(1)
5292 .returning(|_, _| Ok(()));
5293
5294 mock_service_control
5296 .expect_start()
5297 .with(eq("antnode1"), eq(false))
5298 .times(1)
5299 .returning(|_, _| Ok(()));
5300 mock_service_control
5301 .expect_wait()
5302 .with(eq(3000))
5303 .times(1)
5304 .returning(|_| ());
5305 mock_service_control
5306 .expect_get_process_pid()
5307 .with(eq(current_node_bin.to_path_buf().clone()))
5308 .times(1)
5309 .returning(|_| Ok(100));
5310
5311 mock_rpc_client.expect_node_info().times(1).returning(|| {
5312 Ok(NodeInfo {
5313 pid: 2000,
5314 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
5315 data_path: PathBuf::from("/var/antctl/services/antnode1"),
5316 log_path: PathBuf::from("/var/log/antnode/antnode1"),
5317 version: target_version.to_string(),
5318 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
5320 })
5321 });
5322 mock_rpc_client
5323 .expect_network_info()
5324 .times(1)
5325 .returning(|| {
5326 Ok(NetworkInfo {
5327 connected_peers: Vec::new(),
5328 listeners: Vec::new(),
5329 })
5330 });
5331
5332 let service_data = NodeServiceData {
5333 alpha: false,
5334 auto_restart: false,
5335 connected_peers: None,
5336 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
5337 evm_network: EvmNetwork::ArbitrumOne,
5338 relay: false,
5339 initial_peers_config: Default::default(),
5340 listen_addr: None,
5341 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
5342 log_format: None,
5343 max_archived_log_files: None,
5344 max_log_files: None,
5345 metrics_port: Some(12000),
5346 network_id: None,
5347 node_ip: None,
5348 node_port: None,
5349 number: 1,
5350 peer_id: Some(PeerId::from_str(
5351 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
5352 )?),
5353 pid: Some(1000),
5354 rewards_address: RewardsAddress::from_str(
5355 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
5356 )?,
5357 reward_balance: Some(AttoTokens::zero()),
5358 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
5359 antnode_path: current_node_bin.to_path_buf(),
5360 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
5361 service_name: "antnode1".to_string(),
5362 status: ServiceStatus::Running,
5363 no_upnp: false,
5364 user: Some("ant".to_string()),
5365 user_mode: false,
5366 version: current_version.to_string(),
5367 write_older_cache_files: false,
5368 };
5369 let service_data = Arc::new(RwLock::new(service_data));
5370 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
5371
5372 let mut service_manager = ServiceManager::new(
5373 service,
5374 Box::new(mock_service_control),
5375 VerbosityLevel::Normal,
5376 );
5377
5378 service_manager
5379 .upgrade(UpgradeOptions {
5380 auto_restart: false,
5381 env_variables: None,
5382 force: false,
5383 start_service: true,
5384 target_bin_path: target_node_bin.to_path_buf(),
5385 target_version: Version::parse(target_version).unwrap(),
5386 })
5387 .await?;
5388
5389 let service_data = service_data.read().await;
5390 assert_eq!(
5391 service_data.rpc_socket_addr,
5392 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081)
5393 );
5394
5395 Ok(())
5396 }
5397
5398 #[tokio::test]
5399 async fn upgrade_should_retain_auto_restart() -> Result<()> {
5400 let current_version = "0.1.0";
5401 let target_version = "0.2.0";
5402
5403 let tmp_data_dir = assert_fs::TempDir::new()?;
5404 let current_install_dir = tmp_data_dir.child("antnode_install");
5405 current_install_dir.create_dir_all()?;
5406
5407 let current_node_bin = current_install_dir.child("antnode");
5408 current_node_bin.write_binary(b"fake antnode binary")?;
5409 let target_node_bin = tmp_data_dir.child("antnode");
5410 target_node_bin.write_binary(b"fake antnode binary")?;
5411
5412 let mut mock_service_control = MockServiceControl::new();
5413 let mut mock_rpc_client = MockRpcClient::new();
5414
5415 mock_service_control
5417 .expect_get_process_pid()
5418 .with(eq(current_node_bin.to_path_buf().clone()))
5419 .times(1)
5420 .returning(|_| Ok(1000));
5421 mock_service_control
5422 .expect_stop()
5423 .with(eq("antnode1"), eq(false))
5424 .times(1)
5425 .returning(|_, _| Ok(()));
5426
5427 mock_service_control
5429 .expect_uninstall()
5430 .with(eq("antnode1"), eq(false))
5431 .times(1)
5432 .returning(|_, _| Ok(()));
5433 mock_service_control
5434 .expect_install()
5435 .with(
5436 eq(ServiceInstallCtx {
5437 args: vec![
5438 OsString::from("--rpc"),
5439 OsString::from("127.0.0.1:8081"),
5440 OsString::from("--root-dir"),
5441 OsString::from("/var/antctl/services/antnode1"),
5442 OsString::from("--log-output-dest"),
5443 OsString::from("/var/log/antnode/antnode1"),
5444 OsString::from("--rewards-address"),
5445 OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"),
5446 OsString::from("evm-arbitrum-one"),
5447 ],
5448 autostart: true,
5449 contents: None,
5450 environment: None,
5451 label: "antnode1".parse()?,
5452 program: current_node_bin.to_path_buf(),
5453 username: Some("ant".to_string()),
5454 working_directory: None,
5455 disable_restart_on_failure: true,
5456 }),
5457 eq(false),
5458 )
5459 .times(1)
5460 .returning(|_, _| Ok(()));
5461
5462 mock_service_control
5464 .expect_start()
5465 .with(eq("antnode1"), eq(false))
5466 .times(1)
5467 .returning(|_, _| Ok(()));
5468 mock_service_control
5469 .expect_wait()
5470 .with(eq(3000))
5471 .times(1)
5472 .returning(|_| ());
5473 mock_service_control
5474 .expect_get_process_pid()
5475 .with(eq(current_node_bin.to_path_buf().clone()))
5476 .times(1)
5477 .returning(|_| Ok(100));
5478
5479 mock_rpc_client.expect_node_info().times(1).returning(|| {
5480 Ok(NodeInfo {
5481 pid: 2000,
5482 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
5483 data_path: PathBuf::from("/var/antctl/services/antnode1"),
5484 log_path: PathBuf::from("/var/log/antnode/antnode1"),
5485 version: target_version.to_string(),
5486 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
5488 })
5489 });
5490 mock_rpc_client
5491 .expect_network_info()
5492 .times(1)
5493 .returning(|| {
5494 Ok(NetworkInfo {
5495 connected_peers: Vec::new(),
5496 listeners: Vec::new(),
5497 })
5498 });
5499
5500 let service_data = NodeServiceData {
5501 alpha: false,
5502 auto_restart: true,
5503 connected_peers: None,
5504 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
5505 evm_network: EvmNetwork::ArbitrumOne,
5506 relay: false,
5507 initial_peers_config: Default::default(),
5508 listen_addr: None,
5509 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
5510 log_format: None,
5511 max_archived_log_files: None,
5512 max_log_files: None,
5513 metrics_port: None,
5514 network_id: None,
5515 node_ip: None,
5516 node_port: None,
5517 number: 1,
5518 peer_id: Some(PeerId::from_str(
5519 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
5520 )?),
5521 pid: Some(1000),
5522 rewards_address: RewardsAddress::from_str(
5523 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
5524 )?,
5525 reward_balance: Some(AttoTokens::zero()),
5526 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
5527 antnode_path: current_node_bin.to_path_buf(),
5528 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
5529 service_name: "antnode1".to_string(),
5530 status: ServiceStatus::Running,
5531 no_upnp: false,
5532 user: Some("ant".to_string()),
5533 user_mode: false,
5534 version: current_version.to_string(),
5535 write_older_cache_files: false,
5536 };
5537 let service_data = Arc::new(RwLock::new(service_data));
5538 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
5539
5540 let mut service_manager = ServiceManager::new(
5541 service,
5542 Box::new(mock_service_control),
5543 VerbosityLevel::Normal,
5544 );
5545
5546 service_manager
5547 .upgrade(UpgradeOptions {
5548 auto_restart: true,
5549 env_variables: None,
5550 force: false,
5551 start_service: true,
5552 target_bin_path: target_node_bin.to_path_buf(),
5553 target_version: Version::parse(target_version).unwrap(),
5554 })
5555 .await?;
5556
5557 let service_data = service_data.read().await;
5558 assert!(service_data.auto_restart,);
5559
5560 Ok(())
5561 }
5562
5563 #[tokio::test]
5564 async fn upgrade_should_retain_evm_network_settings() -> Result<()> {
5565 let current_version = "0.1.0";
5566 let target_version = "0.2.0";
5567
5568 let tmp_data_dir = assert_fs::TempDir::new()?;
5569 let current_install_dir = tmp_data_dir.child("antnode_install");
5570 current_install_dir.create_dir_all()?;
5571
5572 let current_node_bin = current_install_dir.child("antnode");
5573 current_node_bin.write_binary(b"fake antnode binary")?;
5574 let target_node_bin = tmp_data_dir.child("antnode");
5575 target_node_bin.write_binary(b"fake antnode binary")?;
5576
5577 let mut mock_service_control = MockServiceControl::new();
5578 let mut mock_rpc_client = MockRpcClient::new();
5579
5580 mock_service_control
5582 .expect_get_process_pid()
5583 .with(eq(current_node_bin.to_path_buf().clone()))
5584 .times(1)
5585 .returning(|_| Ok(1000));
5586 mock_service_control
5587 .expect_stop()
5588 .with(eq("antnode1"), eq(false))
5589 .times(1)
5590 .returning(|_, _| Ok(()));
5591
5592 mock_service_control
5594 .expect_uninstall()
5595 .with(eq("antnode1"), eq(false))
5596 .times(1)
5597 .returning(|_, _| Ok(()));
5598 mock_service_control
5599 .expect_install()
5600 .with(
5601 eq(ServiceInstallCtx {
5602 args: vec![
5603 OsString::from("--rpc"),
5604 OsString::from("127.0.0.1:8081"),
5605 OsString::from("--root-dir"),
5606 OsString::from("/var/antctl/services/antnode1"),
5607 OsString::from("--log-output-dest"),
5608 OsString::from("/var/log/antnode/antnode1"),
5609 OsString::from("--rewards-address"),
5610 OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"),
5611 OsString::from("evm-custom"),
5612 OsString::from("--rpc-url"),
5613 OsString::from("http://localhost:8545/"),
5614 OsString::from("--payment-token-address"),
5615 OsString::from("0x5FbDB2315678afecb367f032d93F642f64180aa3"),
5616 OsString::from("--data-payments-address"),
5617 OsString::from("0x8464135c8F25Da09e49BC8782676a84730C318bC"),
5618 ],
5619 autostart: true,
5620 contents: None,
5621 environment: None,
5622 label: "antnode1".parse()?,
5623 program: current_node_bin.to_path_buf(),
5624 username: Some("ant".to_string()),
5625 working_directory: None,
5626 disable_restart_on_failure: true,
5627 }),
5628 eq(false),
5629 )
5630 .times(1)
5631 .returning(|_, _| Ok(()));
5632
5633 mock_service_control
5635 .expect_start()
5636 .with(eq("antnode1"), eq(false))
5637 .times(1)
5638 .returning(|_, _| Ok(()));
5639 mock_service_control
5640 .expect_wait()
5641 .with(eq(3000))
5642 .times(1)
5643 .returning(|_| ());
5644 mock_service_control
5645 .expect_get_process_pid()
5646 .with(eq(current_node_bin.to_path_buf().clone()))
5647 .times(1)
5648 .returning(|_| Ok(100));
5649
5650 mock_rpc_client.expect_node_info().times(1).returning(|| {
5651 Ok(NodeInfo {
5652 pid: 2000,
5653 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
5654 data_path: PathBuf::from("/var/antctl/services/antnode1"),
5655 log_path: PathBuf::from("/var/log/antnode/antnode1"),
5656 version: target_version.to_string(),
5657 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
5659 })
5660 });
5661 mock_rpc_client
5662 .expect_network_info()
5663 .times(1)
5664 .returning(|| {
5665 Ok(NetworkInfo {
5666 connected_peers: Vec::new(),
5667 listeners: Vec::new(),
5668 })
5669 });
5670
5671 let service_data = NodeServiceData {
5672 alpha: false,
5673 auto_restart: true,
5674 connected_peers: None,
5675 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
5676 evm_network: EvmNetwork::Custom(CustomNetwork {
5677 rpc_url_http: "http://localhost:8545".parse()?,
5678 payment_token_address: RewardsAddress::from_str(
5679 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
5680 )?,
5681 data_payments_address: RewardsAddress::from_str(
5682 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
5683 )?,
5684 }),
5685 relay: false,
5686 initial_peers_config: Default::default(),
5687 listen_addr: None,
5688 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
5689 log_format: None,
5690 max_archived_log_files: None,
5691 max_log_files: None,
5692 metrics_port: None,
5693 network_id: None,
5694 node_ip: None,
5695 node_port: None,
5696 number: 1,
5697 peer_id: Some(PeerId::from_str(
5698 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
5699 )?),
5700 pid: Some(1000),
5701 rewards_address: RewardsAddress::from_str(
5702 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
5703 )?,
5704 reward_balance: Some(AttoTokens::zero()),
5705
5706 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
5707 antnode_path: current_node_bin.to_path_buf(),
5708 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
5709 service_name: "antnode1".to_string(),
5710 status: ServiceStatus::Running,
5711 no_upnp: false,
5712 user: Some("ant".to_string()),
5713 user_mode: false,
5714 version: current_version.to_string(),
5715 write_older_cache_files: false,
5716 };
5717 let service_data = Arc::new(RwLock::new(service_data));
5718 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
5719
5720 let mut service_manager = ServiceManager::new(
5721 service,
5722 Box::new(mock_service_control),
5723 VerbosityLevel::Normal,
5724 );
5725
5726 service_manager
5727 .upgrade(UpgradeOptions {
5728 auto_restart: true,
5729 env_variables: None,
5730 force: false,
5731 start_service: true,
5732 target_bin_path: target_node_bin.to_path_buf(),
5733 target_version: Version::parse(target_version).unwrap(),
5734 })
5735 .await?;
5736
5737 let service_data = service_data.read().await;
5738 assert!(service_data.auto_restart,);
5739
5740 Ok(())
5741 }
5742
5743 #[tokio::test]
5744 async fn upgrade_should_retain_the_rewards_address() -> Result<()> {
5745 let current_version = "0.1.0";
5746 let target_version = "0.2.0";
5747
5748 let tmp_data_dir = assert_fs::TempDir::new()?;
5749 let current_install_dir = tmp_data_dir.child("antnode_install");
5750 current_install_dir.create_dir_all()?;
5751
5752 let current_node_bin = current_install_dir.child("antnode");
5753 current_node_bin.write_binary(b"fake antnode binary")?;
5754 let target_node_bin = tmp_data_dir.child("antnode");
5755 target_node_bin.write_binary(b"fake antnode binary")?;
5756
5757 let mut mock_service_control = MockServiceControl::new();
5758 let mut mock_rpc_client = MockRpcClient::new();
5759
5760 mock_service_control
5762 .expect_get_process_pid()
5763 .with(eq(current_node_bin.to_path_buf().clone()))
5764 .times(1)
5765 .returning(|_| Ok(1000));
5766 mock_service_control
5767 .expect_stop()
5768 .with(eq("antnode1"), eq(false))
5769 .times(1)
5770 .returning(|_, _| Ok(()));
5771
5772 mock_service_control
5774 .expect_uninstall()
5775 .with(eq("antnode1"), eq(false))
5776 .times(1)
5777 .returning(|_, _| Ok(()));
5778 mock_service_control
5779 .expect_install()
5780 .with(
5781 eq(ServiceInstallCtx {
5782 args: vec![
5783 OsString::from("--rpc"),
5784 OsString::from("127.0.0.1:8081"),
5785 OsString::from("--root-dir"),
5786 OsString::from("/var/antctl/services/antnode1"),
5787 OsString::from("--log-output-dest"),
5788 OsString::from("/var/log/antnode/antnode1"),
5789 OsString::from("--rewards-address"),
5790 OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"),
5791 OsString::from("evm-custom"),
5792 OsString::from("--rpc-url"),
5793 OsString::from("http://localhost:8545/"),
5794 OsString::from("--payment-token-address"),
5795 OsString::from("0x5FbDB2315678afecb367f032d93F642f64180aa3"),
5796 OsString::from("--data-payments-address"),
5797 OsString::from("0x8464135c8F25Da09e49BC8782676a84730C318bC"),
5798 ],
5799 autostart: true,
5800 contents: None,
5801 environment: None,
5802 label: "antnode1".parse()?,
5803 program: current_node_bin.to_path_buf(),
5804 username: Some("ant".to_string()),
5805 working_directory: None,
5806 disable_restart_on_failure: true,
5807 }),
5808 eq(false),
5809 )
5810 .times(1)
5811 .returning(|_, _| Ok(()));
5812
5813 mock_service_control
5815 .expect_start()
5816 .with(eq("antnode1"), eq(false))
5817 .times(1)
5818 .returning(|_, _| Ok(()));
5819 mock_service_control
5820 .expect_wait()
5821 .with(eq(3000))
5822 .times(1)
5823 .returning(|_| ());
5824 mock_service_control
5825 .expect_get_process_pid()
5826 .with(eq(current_node_bin.to_path_buf().clone()))
5827 .times(1)
5828 .returning(|_| Ok(100));
5829
5830 mock_rpc_client.expect_node_info().times(1).returning(|| {
5831 Ok(NodeInfo {
5832 pid: 2000,
5833 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
5834 data_path: PathBuf::from("/var/antctl/services/antnode1"),
5835 log_path: PathBuf::from("/var/log/antnode/antnode1"),
5836 version: target_version.to_string(),
5837 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
5839 })
5840 });
5841 mock_rpc_client
5842 .expect_network_info()
5843 .times(1)
5844 .returning(|| {
5845 Ok(NetworkInfo {
5846 connected_peers: Vec::new(),
5847 listeners: Vec::new(),
5848 })
5849 });
5850
5851 let service_data = NodeServiceData {
5852 alpha: false,
5853 auto_restart: true,
5854 connected_peers: None,
5855 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
5856 evm_network: EvmNetwork::Custom(CustomNetwork {
5857 rpc_url_http: "http://localhost:8545".parse()?,
5858 payment_token_address: RewardsAddress::from_str(
5859 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
5860 )?,
5861 data_payments_address: RewardsAddress::from_str(
5862 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
5863 )?,
5864 }),
5865 relay: false,
5866 initial_peers_config: Default::default(),
5867 listen_addr: None,
5868 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
5869 log_format: None,
5870 max_archived_log_files: None,
5871 max_log_files: None,
5872 metrics_port: None,
5873 network_id: None,
5874 node_ip: None,
5875 node_port: None,
5876 number: 1,
5877 peer_id: Some(PeerId::from_str(
5878 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
5879 )?),
5880 pid: Some(1000),
5881 rewards_address: RewardsAddress::from_str(
5882 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
5883 )?,
5884 reward_balance: Some(AttoTokens::zero()),
5885
5886 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
5887 antnode_path: current_node_bin.to_path_buf(),
5888 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
5889 service_name: "antnode1".to_string(),
5890 status: ServiceStatus::Running,
5891 no_upnp: false,
5892 user: Some("ant".to_string()),
5893 user_mode: false,
5894 version: current_version.to_string(),
5895 write_older_cache_files: false,
5896 };
5897 let service_data = Arc::new(RwLock::new(service_data));
5898 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
5899
5900 let mut service_manager = ServiceManager::new(
5901 service,
5902 Box::new(mock_service_control),
5903 VerbosityLevel::Normal,
5904 );
5905
5906 service_manager
5907 .upgrade(UpgradeOptions {
5908 auto_restart: true,
5909 env_variables: None,
5910 force: false,
5911 start_service: true,
5912 target_bin_path: target_node_bin.to_path_buf(),
5913 target_version: Version::parse(target_version).unwrap(),
5914 })
5915 .await?;
5916
5917 let service_data = service_data.read().await;
5918 assert!(service_data.auto_restart,);
5919
5920 Ok(())
5921 }
5922
5923 #[tokio::test]
5924 async fn upgrade_should_use_dynamic_startup_delay_if_set() -> Result<()> {
5925 let current_version = "0.1.0";
5926 let target_version = "0.2.0";
5927
5928 let tmp_data_dir = assert_fs::TempDir::new()?;
5929 let current_install_dir = tmp_data_dir.child("antnode_install");
5930 current_install_dir.create_dir_all()?;
5931
5932 let current_node_bin = current_install_dir.child("antnode");
5933 current_node_bin.write_binary(b"fake antnode binary")?;
5934 let target_node_bin = tmp_data_dir.child("antnode");
5935 target_node_bin.write_binary(b"fake antnode binary")?;
5936
5937 let mut mock_service_control = MockServiceControl::new();
5938 let mut mock_rpc_client = MockRpcClient::new();
5939
5940 mock_service_control
5942 .expect_get_process_pid()
5943 .with(eq(current_node_bin.to_path_buf().clone()))
5944 .times(1)
5945 .returning(|_| Ok(1000));
5946 mock_service_control
5947 .expect_stop()
5948 .with(eq("antnode1"), eq(false))
5949 .times(1)
5950 .returning(|_, _| Ok(()));
5951
5952 mock_service_control
5954 .expect_uninstall()
5955 .with(eq("antnode1"), eq(false))
5956 .times(1)
5957 .returning(|_, _| Ok(()));
5958 mock_service_control
5959 .expect_install()
5960 .with(
5961 eq(ServiceInstallCtx {
5962 args: vec![
5963 OsString::from("--rpc"),
5964 OsString::from("127.0.0.1:8081"),
5965 OsString::from("--root-dir"),
5966 OsString::from("/var/antctl/services/antnode1"),
5967 OsString::from("--log-output-dest"),
5968 OsString::from("/var/log/antnode/antnode1"),
5969 OsString::from("--rewards-address"),
5970 OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"),
5971 OsString::from("evm-arbitrum-one"),
5972 ],
5973 autostart: false,
5974 contents: None,
5975 environment: None,
5976 label: "antnode1".parse()?,
5977 program: current_node_bin.to_path_buf(),
5978 username: Some("ant".to_string()),
5979 working_directory: None,
5980 disable_restart_on_failure: true,
5981 }),
5982 eq(false),
5983 )
5984 .times(1)
5985 .returning(|_, _| Ok(()));
5986
5987 mock_service_control
5989 .expect_start()
5990 .with(eq("antnode1"), eq(false))
5991 .times(1)
5992 .returning(|_, _| Ok(()));
5993 mock_service_control
5994 .expect_wait()
5995 .with(eq(3000))
5996 .times(1)
5997 .returning(|_| ());
5998 mock_service_control
5999 .expect_get_process_pid()
6000 .with(eq(current_node_bin.to_path_buf().clone()))
6001 .times(1)
6002 .returning(|_| Ok(100));
6003 mock_rpc_client
6004 .expect_is_node_connected_to_network()
6005 .times(1)
6006 .returning(|_| Ok(()));
6007 mock_rpc_client.expect_node_info().times(1).returning(|| {
6008 Ok(NodeInfo {
6009 pid: 2000,
6010 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
6011 data_path: PathBuf::from("/var/antctl/services/antnode1"),
6012 log_path: PathBuf::from("/var/log/antnode/antnode1"),
6013 version: target_version.to_string(),
6014 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
6016 })
6017 });
6018 mock_rpc_client
6019 .expect_network_info()
6020 .times(1)
6021 .returning(|| {
6022 Ok(NetworkInfo {
6023 connected_peers: Vec::new(),
6024 listeners: Vec::new(),
6025 })
6026 });
6027
6028 let service_data = NodeServiceData {
6029 alpha: false,
6030 auto_restart: false,
6031 connected_peers: None,
6032 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
6033 evm_network: EvmNetwork::ArbitrumOne,
6034 relay: false,
6035 initial_peers_config: Default::default(),
6036 listen_addr: None,
6037 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
6038 log_format: None,
6039 max_archived_log_files: None,
6040 max_log_files: None,
6041 metrics_port: None,
6042 network_id: None,
6043 node_ip: None,
6044 node_port: None,
6045 number: 1,
6046 peer_id: Some(PeerId::from_str(
6047 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
6048 )?),
6049 pid: Some(1000),
6050 rewards_address: RewardsAddress::from_str(
6051 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
6052 )?,
6053 reward_balance: Some(AttoTokens::zero()),
6054 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
6055 antnode_path: current_node_bin.to_path_buf(),
6056 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
6057 service_name: "antnode1".to_string(),
6058 status: ServiceStatus::Running,
6059 no_upnp: false,
6060 user: Some("ant".to_string()),
6061 user_mode: false,
6062 version: current_version.to_string(),
6063 write_older_cache_files: false,
6064 };
6065 let service_data = Arc::new(RwLock::new(service_data));
6066 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client))
6067 .with_connection_timeout(Duration::from_secs(
6068 DEFAULT_NODE_STARTUP_CONNECTION_TIMEOUT_S,
6069 ));
6070
6071 let mut service_manager = ServiceManager::new(
6072 service,
6073 Box::new(mock_service_control),
6074 VerbosityLevel::Normal,
6075 );
6076
6077 service_manager
6078 .upgrade(UpgradeOptions {
6079 auto_restart: false,
6080 env_variables: None,
6081 force: false,
6082 start_service: true,
6083 target_bin_path: target_node_bin.to_path_buf(),
6084 target_version: Version::parse(target_version).unwrap(),
6085 })
6086 .await?;
6087
6088 Ok(())
6089 }
6090
6091 #[tokio::test]
6092 async fn upgrade_should_retain_write_older_cache_files() -> Result<()> {
6093 let current_version = "0.1.0";
6094 let target_version = "0.2.0";
6095
6096 let tmp_data_dir = assert_fs::TempDir::new()?;
6097 let current_install_dir = tmp_data_dir.child("antnode_install");
6098 current_install_dir.create_dir_all()?;
6099
6100 let current_node_bin = current_install_dir.child("antnode");
6101 current_node_bin.write_binary(b"fake antnode binary")?;
6102 let target_node_bin = tmp_data_dir.child("antnode");
6103 target_node_bin.write_binary(b"fake antnode binary")?;
6104
6105 let mut mock_service_control = MockServiceControl::new();
6106 let mut mock_rpc_client = MockRpcClient::new();
6107
6108 mock_service_control
6110 .expect_get_process_pid()
6111 .with(eq(current_node_bin.to_path_buf().clone()))
6112 .times(1)
6113 .returning(|_| Ok(1000));
6114 mock_service_control
6115 .expect_stop()
6116 .with(eq("antnode1"), eq(false))
6117 .times(1)
6118 .returning(|_, _| Ok(()));
6119
6120 mock_service_control
6122 .expect_uninstall()
6123 .with(eq("antnode1"), eq(false))
6124 .times(1)
6125 .returning(|_, _| Ok(()));
6126 mock_service_control
6127 .expect_install()
6128 .with(
6129 eq(ServiceInstallCtx {
6130 args: vec![
6131 OsString::from("--rpc"),
6132 OsString::from("127.0.0.1:8081"),
6133 OsString::from("--root-dir"),
6134 OsString::from("/var/antctl/services/antnode1"),
6135 OsString::from("--log-output-dest"),
6136 OsString::from("/var/log/antnode/antnode1"),
6137 OsString::from("--metrics-server-port"),
6138 OsString::from("12000"),
6139 OsString::from("--rewards-address"),
6140 OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"),
6141 OsString::from("--write-older-cache-files"),
6142 OsString::from("evm-arbitrum-one"),
6143 ],
6144 autostart: false,
6145 contents: None,
6146 environment: None,
6147 label: "antnode1".parse()?,
6148 program: current_node_bin.to_path_buf(),
6149 username: Some("ant".to_string()),
6150 working_directory: None,
6151 disable_restart_on_failure: true,
6152 }),
6153 eq(false),
6154 )
6155 .times(1)
6156 .returning(|_, _| Ok(()));
6157
6158 mock_service_control
6160 .expect_start()
6161 .with(eq("antnode1"), eq(false))
6162 .times(1)
6163 .returning(|_, _| Ok(()));
6164 mock_service_control
6165 .expect_wait()
6166 .with(eq(3000))
6167 .times(1)
6168 .returning(|_| ());
6169 mock_service_control
6170 .expect_get_process_pid()
6171 .with(eq(current_node_bin.to_path_buf().clone()))
6172 .times(1)
6173 .returning(|_| Ok(100));
6174
6175 mock_rpc_client.expect_node_info().times(1).returning(|| {
6176 Ok(NodeInfo {
6177 pid: 2000,
6178 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
6179 data_path: PathBuf::from("/var/antctl/services/antnode1"),
6180 log_path: PathBuf::from("/var/log/antnode/antnode1"),
6181 version: target_version.to_string(),
6182 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
6184 })
6185 });
6186 mock_rpc_client
6187 .expect_network_info()
6188 .times(1)
6189 .returning(|| {
6190 Ok(NetworkInfo {
6191 connected_peers: Vec::new(),
6192 listeners: Vec::new(),
6193 })
6194 });
6195
6196 let service_data = NodeServiceData {
6197 alpha: false,
6198 auto_restart: false,
6199 connected_peers: None,
6200 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
6201 evm_network: EvmNetwork::ArbitrumOne,
6202 relay: false,
6203 listen_addr: None,
6204 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
6205 log_format: None,
6206 max_archived_log_files: None,
6207 max_log_files: None,
6208 metrics_port: Some(12000),
6209 network_id: None,
6210 node_ip: None,
6211 node_port: None,
6212 number: 1,
6213 peer_id: Some(PeerId::from_str(
6214 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
6215 )?),
6216 initial_peers_config: InitialPeersConfig::default(),
6217 pid: Some(1000),
6218 rewards_address: RewardsAddress::from_str(
6219 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
6220 )?,
6221 reward_balance: Some(AttoTokens::zero()),
6222 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
6223 antnode_path: current_node_bin.to_path_buf(),
6224 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
6225 service_name: "antnode1".to_string(),
6226 status: ServiceStatus::Running,
6227 no_upnp: false,
6228 user: Some("ant".to_string()),
6229 user_mode: false,
6230 version: current_version.to_string(),
6231 write_older_cache_files: true,
6232 };
6233 let service_data = Arc::new(RwLock::new(service_data));
6234 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
6235
6236 let mut service_manager = ServiceManager::new(
6237 service,
6238 Box::new(mock_service_control),
6239 VerbosityLevel::Normal,
6240 );
6241
6242 service_manager
6243 .upgrade(UpgradeOptions {
6244 auto_restart: false,
6245 env_variables: None,
6246 force: false,
6247 start_service: true,
6248 target_bin_path: target_node_bin.to_path_buf(),
6249 target_version: Version::parse(target_version).unwrap(),
6250 })
6251 .await?;
6252
6253 let service_data = service_data.read().await;
6254 assert!(service_data.write_older_cache_files,);
6255
6256 Ok(())
6257 }
6258
6259 #[tokio::test]
6260 async fn remove_should_remove_an_added_node() -> Result<()> {
6261 let temp_dir = assert_fs::TempDir::new()?;
6262 let log_dir = temp_dir.child("antnode1-logs");
6263 log_dir.create_dir_all()?;
6264 let data_dir = temp_dir.child("antnode1-data");
6265 data_dir.create_dir_all()?;
6266 let antnode_bin = data_dir.child("antnode");
6267 antnode_bin.write_binary(b"fake antnode binary")?;
6268
6269 let mut mock_service_control = MockServiceControl::new();
6270 mock_service_control
6271 .expect_uninstall()
6272 .with(eq("antnode1"), eq(false))
6273 .times(1)
6274 .returning(|_, _| Ok(()));
6275
6276 let service_data = NodeServiceData {
6277 alpha: false,
6278 auto_restart: false,
6279 connected_peers: None,
6280 data_dir_path: data_dir.to_path_buf(),
6281 evm_network: EvmNetwork::Custom(CustomNetwork {
6282 rpc_url_http: "http://localhost:8545".parse()?,
6283 payment_token_address: RewardsAddress::from_str(
6284 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
6285 )?,
6286 data_payments_address: RewardsAddress::from_str(
6287 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
6288 )?,
6289 }),
6290 relay: false,
6291 initial_peers_config: Default::default(),
6292 listen_addr: None,
6293 log_dir_path: log_dir.to_path_buf(),
6294 log_format: None,
6295 max_archived_log_files: None,
6296 max_log_files: None,
6297 metrics_port: None,
6298 network_id: None,
6299 node_ip: None,
6300 node_port: None,
6301 number: 1,
6302 peer_id: None,
6303 pid: None,
6304 rewards_address: RewardsAddress::from_str(
6305 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
6306 )?,
6307 reward_balance: Some(AttoTokens::zero()),
6308 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
6309 antnode_path: antnode_bin.to_path_buf(),
6310 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
6311 status: ServiceStatus::Stopped,
6312 service_name: "antnode1".to_string(),
6313 version: "0.98.1".to_string(),
6314 no_upnp: false,
6315 user: Some("ant".to_string()),
6316 user_mode: false,
6317 write_older_cache_files: false,
6318 };
6319 let service_data = Arc::new(RwLock::new(service_data));
6320 let service = NodeService::new(Arc::clone(&service_data), Box::new(MockRpcClient::new()));
6321 let mut service_manager = ServiceManager::new(
6322 service,
6323 Box::new(mock_service_control),
6324 VerbosityLevel::Normal,
6325 );
6326
6327 service_manager.remove(false).await?;
6328
6329 let service_data = service_data.read().await;
6330 assert_matches!(service_data.status, ServiceStatus::Removed);
6331 log_dir.assert(predicate::path::missing());
6332 data_dir.assert(predicate::path::missing());
6333
6334 Ok(())
6335 }
6336
6337 #[tokio::test]
6338 async fn remove_should_return_an_error_if_attempting_to_remove_a_running_node() -> Result<()> {
6339 let mut mock_service_control = MockServiceControl::new();
6340 mock_service_control
6341 .expect_get_process_pid()
6342 .with(eq(PathBuf::from("/var/antctl/services/antnode1/antnode")))
6343 .times(1)
6344 .returning(|_| Ok(1000));
6345
6346 let service_data = NodeServiceData {
6347 alpha: false,
6348 auto_restart: false,
6349 connected_peers: None,
6350 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
6351 evm_network: EvmNetwork::Custom(CustomNetwork {
6352 rpc_url_http: "http://localhost:8545".parse()?,
6353 payment_token_address: RewardsAddress::from_str(
6354 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
6355 )?,
6356 data_payments_address: RewardsAddress::from_str(
6357 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
6358 )?,
6359 }),
6360 relay: false,
6361 initial_peers_config: Default::default(),
6362 listen_addr: None,
6363 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
6364 log_format: None,
6365 max_archived_log_files: None,
6366 max_log_files: None,
6367 metrics_port: None,
6368 network_id: None,
6369 node_ip: None,
6370 node_port: None,
6371 number: 1,
6372 pid: Some(1000),
6373 peer_id: Some(PeerId::from_str(
6374 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
6375 )?),
6376 rewards_address: RewardsAddress::from_str(
6377 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
6378 )?,
6379 reward_balance: Some(AttoTokens::zero()),
6380 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
6381 antnode_path: PathBuf::from("/var/antctl/services/antnode1/antnode"),
6382 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
6383 service_name: "antnode1".to_string(),
6384 status: ServiceStatus::Running,
6385 no_upnp: false,
6386 user: Some("ant".to_string()),
6387 user_mode: false,
6388 version: "0.98.1".to_string(),
6389 write_older_cache_files: false,
6390 };
6391 let service_data = Arc::new(RwLock::new(service_data));
6392 let service = NodeService::new(Arc::clone(&service_data), Box::new(MockRpcClient::new()));
6393 let mut service_manager = ServiceManager::new(
6394 service,
6395 Box::new(mock_service_control),
6396 VerbosityLevel::Normal,
6397 );
6398
6399 let result = service_manager.remove(false).await;
6400 match result {
6401 Ok(_) => panic!("This test should result in an error"),
6402 Err(e) => assert_eq!(
6403 "Unable to remove a running service [\"antnode1\"], stop this service first before removing",
6404 e.to_string()
6405 ),
6406 }
6407
6408 Ok(())
6409 }
6410
6411 #[tokio::test]
6412 async fn remove_should_return_an_error_for_a_node_that_was_marked_running_but_was_not_actually_running()
6413 -> Result<()> {
6414 let temp_dir = assert_fs::TempDir::new()?;
6415 let log_dir = temp_dir.child("antnode1-logs");
6416 log_dir.create_dir_all()?;
6417 let data_dir = temp_dir.child("antnode1-data");
6418 data_dir.create_dir_all()?;
6419 let antnode_bin = data_dir.child("antnode");
6420 antnode_bin.write_binary(b"fake antnode binary")?;
6421
6422 let mut mock_service_control = MockServiceControl::new();
6423 mock_service_control
6424 .expect_get_process_pid()
6425 .with(eq(PathBuf::from("/var/antctl/services/antnode1/antnode")))
6426 .times(1)
6427 .returning(|_| {
6428 Err(ServiceError::ServiceProcessNotFound(
6429 "Could not find process at '/var/antctl/services/antnode1/antnode'".to_string(),
6430 ))
6431 });
6432
6433 let service_data = NodeServiceData {
6434 alpha: false,
6435 auto_restart: false,
6436 connected_peers: None,
6437 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
6438 evm_network: EvmNetwork::Custom(CustomNetwork {
6439 rpc_url_http: "http://localhost:8545".parse()?,
6440 payment_token_address: RewardsAddress::from_str(
6441 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
6442 )?,
6443 data_payments_address: RewardsAddress::from_str(
6444 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
6445 )?,
6446 }),
6447 relay: false,
6448 initial_peers_config: Default::default(),
6449 listen_addr: None,
6450 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
6451 log_format: None,
6452 max_archived_log_files: None,
6453 max_log_files: None,
6454 metrics_port: None,
6455 network_id: None,
6456 node_ip: None,
6457 node_port: None,
6458 number: 1,
6459 pid: Some(1000),
6460 peer_id: Some(PeerId::from_str(
6461 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
6462 )?),
6463 rewards_address: RewardsAddress::from_str(
6464 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
6465 )?,
6466 reward_balance: Some(AttoTokens::zero()),
6467 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
6468 antnode_path: PathBuf::from("/var/antctl/services/antnode1/antnode"),
6469 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
6470 service_name: "antnode1".to_string(),
6471 status: ServiceStatus::Running,
6472 no_upnp: false,
6473 user: Some("ant".to_string()),
6474 user_mode: false,
6475 version: "0.98.1".to_string(),
6476 write_older_cache_files: false,
6477 };
6478 let service_data = Arc::new(RwLock::new(service_data));
6479 let service = NodeService::new(Arc::clone(&service_data), Box::new(MockRpcClient::new()));
6480 let mut service_manager = ServiceManager::new(
6481 service,
6482 Box::new(mock_service_control),
6483 VerbosityLevel::Normal,
6484 );
6485
6486 let result = service_manager.remove(false).await;
6487 match result {
6488 Ok(_) => panic!("This test should result in an error"),
6489 Err(e) => assert_eq!(
6490 "The service status is not as expected. Expected: Running",
6491 e.to_string()
6492 ),
6493 }
6494
6495 Ok(())
6496 }
6497
6498 #[tokio::test]
6499 async fn remove_should_remove_an_added_node_and_keep_directories() -> Result<()> {
6500 let temp_dir = assert_fs::TempDir::new()?;
6501 let log_dir = temp_dir.child("antnode1-logs");
6502 log_dir.create_dir_all()?;
6503 let data_dir = temp_dir.child("antnode1-data");
6504 data_dir.create_dir_all()?;
6505 let antnode_bin = data_dir.child("antnode");
6506 antnode_bin.write_binary(b"fake antnode binary")?;
6507
6508 let mut mock_service_control = MockServiceControl::new();
6509 mock_service_control
6510 .expect_uninstall()
6511 .with(eq("antnode1"), eq(false))
6512 .times(1)
6513 .returning(|_, _| Ok(()));
6514
6515 let service_data = NodeServiceData {
6516 alpha: false,
6517 auto_restart: false,
6518 connected_peers: None,
6519 data_dir_path: data_dir.to_path_buf(),
6520 evm_network: EvmNetwork::Custom(CustomNetwork {
6521 rpc_url_http: "http://localhost:8545".parse()?,
6522 payment_token_address: RewardsAddress::from_str(
6523 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
6524 )?,
6525 data_payments_address: RewardsAddress::from_str(
6526 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
6527 )?,
6528 }),
6529 relay: false,
6530 initial_peers_config: Default::default(),
6531 listen_addr: None,
6532 log_dir_path: log_dir.to_path_buf(),
6533 log_format: None,
6534 max_archived_log_files: None,
6535 max_log_files: None,
6536 metrics_port: None,
6537 network_id: None,
6538 node_ip: None,
6539 node_port: None,
6540 number: 1,
6541 pid: None,
6542 peer_id: None,
6543 rewards_address: RewardsAddress::from_str(
6544 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
6545 )?,
6546 reward_balance: Some(AttoTokens::zero()),
6547 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
6548 antnode_path: antnode_bin.to_path_buf(),
6549 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
6550 service_name: "antnode1".to_string(),
6551 status: ServiceStatus::Stopped,
6552 no_upnp: false,
6553 user: Some("ant".to_string()),
6554 user_mode: false,
6555 version: "0.98.1".to_string(),
6556 write_older_cache_files: false,
6557 };
6558 let service_data = Arc::new(RwLock::new(service_data));
6559 let service = NodeService::new(Arc::clone(&service_data), Box::new(MockRpcClient::new()));
6560 let mut service_manager = ServiceManager::new(
6561 service,
6562 Box::new(mock_service_control),
6563 VerbosityLevel::Normal,
6564 );
6565
6566 service_manager.remove(true).await?;
6567
6568 let service_data = service_data.read().await;
6569 assert_matches!(service_data.status, ServiceStatus::Removed);
6570 log_dir.assert(predicate::path::is_dir());
6571 data_dir.assert(predicate::path::is_dir());
6572
6573 Ok(())
6574 }
6575
6576 #[tokio::test]
6577 async fn remove_should_remove_a_user_mode_service() -> Result<()> {
6578 let temp_dir = assert_fs::TempDir::new()?;
6579 let log_dir = temp_dir.child("antnode1-logs");
6580 log_dir.create_dir_all()?;
6581 let data_dir = temp_dir.child("antnode1-data");
6582 data_dir.create_dir_all()?;
6583 let antnode_bin = data_dir.child("antnode");
6584 antnode_bin.write_binary(b"fake antnode binary")?;
6585
6586 let mut mock_service_control = MockServiceControl::new();
6587 mock_service_control
6588 .expect_uninstall()
6589 .with(eq("antnode1"), eq(true))
6590 .times(1)
6591 .returning(|_, _| Ok(()));
6592
6593 let service_data = NodeServiceData {
6594 alpha: false,
6595 auto_restart: false,
6596 connected_peers: None,
6597 data_dir_path: data_dir.to_path_buf(),
6598 evm_network: EvmNetwork::Custom(CustomNetwork {
6599 rpc_url_http: "http://localhost:8545".parse()?,
6600 payment_token_address: RewardsAddress::from_str(
6601 "0x5FbDB2315678afecb367f032d93F642f64180aa3",
6602 )?,
6603 data_payments_address: RewardsAddress::from_str(
6604 "0x8464135c8F25Da09e49BC8782676a84730C318bC",
6605 )?,
6606 }),
6607 relay: false,
6608 initial_peers_config: Default::default(),
6609 listen_addr: None,
6610 log_dir_path: log_dir.to_path_buf(),
6611 log_format: None,
6612 max_archived_log_files: None,
6613 max_log_files: None,
6614 metrics_port: None,
6615 network_id: None,
6616 node_ip: None,
6617 node_port: None,
6618 number: 1,
6619 pid: None,
6620 peer_id: None,
6621 rewards_address: RewardsAddress::from_str(
6622 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
6623 )?,
6624 reward_balance: Some(AttoTokens::zero()),
6625 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
6626 antnode_path: antnode_bin.to_path_buf(),
6627 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
6628 status: ServiceStatus::Stopped,
6629 service_name: "antnode1".to_string(),
6630 no_upnp: false,
6631 user: None,
6632 user_mode: true,
6633 version: "0.98.1".to_string(),
6634 write_older_cache_files: false,
6635 };
6636 let service_data = Arc::new(RwLock::new(service_data));
6637 let service = NodeService::new(Arc::clone(&service_data), Box::new(MockRpcClient::new()));
6638 let mut service_manager = ServiceManager::new(
6639 service,
6640 Box::new(mock_service_control),
6641 VerbosityLevel::Normal,
6642 );
6643
6644 service_manager.remove(false).await?;
6645
6646 let service_data = service_data.read().await;
6647 assert_matches!(service_data.status, ServiceStatus::Removed);
6648 log_dir.assert(predicate::path::missing());
6649 data_dir.assert(predicate::path::missing());
6650
6651 Ok(())
6652 }
6653
6654 #[tokio::test]
6655 async fn upgrade_should_retain_the_alpha_flag() -> Result<()> {
6656 let current_version = "0.1.0";
6657 let target_version = "0.2.0";
6658
6659 let tmp_data_dir = assert_fs::TempDir::new()?;
6660 let current_install_dir = tmp_data_dir.child("antnode_install");
6661 current_install_dir.create_dir_all()?;
6662
6663 let current_node_bin = current_install_dir.child("antnode");
6664 current_node_bin.write_binary(b"fake antnode binary")?;
6665 let target_node_bin = tmp_data_dir.child("antnode");
6666 target_node_bin.write_binary(b"fake antnode binary")?;
6667
6668 let mut mock_service_control = MockServiceControl::new();
6669 let mut mock_rpc_client = MockRpcClient::new();
6670
6671 mock_service_control
6673 .expect_get_process_pid()
6674 .with(eq(current_node_bin.to_path_buf().clone()))
6675 .times(1)
6676 .returning(|_| Ok(1000));
6677 mock_service_control
6678 .expect_stop()
6679 .with(eq("antnode1"), eq(false))
6680 .times(1)
6681 .returning(|_, _| Ok(()));
6682
6683 mock_service_control
6685 .expect_uninstall()
6686 .with(eq("antnode1"), eq(false))
6687 .times(1)
6688 .returning(|_, _| Ok(()));
6689 mock_service_control
6690 .expect_install()
6691 .with(
6692 eq(ServiceInstallCtx {
6693 args: vec![
6694 OsString::from("--rpc"),
6695 OsString::from("127.0.0.1:8081"),
6696 OsString::from("--root-dir"),
6697 OsString::from("/var/antctl/services/antnode1"),
6698 OsString::from("--log-output-dest"),
6699 OsString::from("/var/log/antnode/antnode1"),
6700 OsString::from("--alpha"),
6701 OsString::from("--rewards-address"),
6702 OsString::from("0x03B770D9cD32077cC0bF330c13C114a87643B124"),
6703 OsString::from("evm-arbitrum-one"),
6704 ],
6705 autostart: false,
6706 contents: None,
6707 environment: None,
6708 label: "antnode1".parse()?,
6709 program: current_node_bin.to_path_buf(),
6710 username: Some("ant".to_string()),
6711 working_directory: None,
6712 disable_restart_on_failure: true,
6713 }),
6714 eq(false),
6715 )
6716 .times(1)
6717 .returning(|_, _| Ok(()));
6718
6719 mock_service_control
6721 .expect_start()
6722 .with(eq("antnode1"), eq(false))
6723 .times(1)
6724 .returning(|_, _| Ok(()));
6725 mock_service_control
6726 .expect_wait()
6727 .with(eq(3000))
6728 .times(1)
6729 .returning(|_| ());
6730 mock_service_control
6731 .expect_get_process_pid()
6732 .with(eq(current_node_bin.to_path_buf().clone()))
6733 .times(1)
6734 .returning(|_| Ok(100));
6735
6736 mock_rpc_client.expect_node_info().times(1).returning(|| {
6737 Ok(NodeInfo {
6738 pid: 2000,
6739 peer_id: PeerId::from_str("12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR")?,
6740 data_path: PathBuf::from("/var/antctl/services/antnode1"),
6741 log_path: PathBuf::from("/var/log/antnode/antnode1"),
6742 version: target_version.to_string(),
6743 uptime: std::time::Duration::from_secs(1), wallet_balance: 0,
6745 })
6746 });
6747 mock_rpc_client
6748 .expect_network_info()
6749 .times(1)
6750 .returning(|| {
6751 Ok(NetworkInfo {
6752 connected_peers: Vec::new(),
6753 listeners: Vec::new(),
6754 })
6755 });
6756
6757 let service_data = NodeServiceData {
6758 alpha: true,
6759 auto_restart: false,
6760 connected_peers: None,
6761 data_dir_path: PathBuf::from("/var/antctl/services/antnode1"),
6762 evm_network: EvmNetwork::ArbitrumOne,
6763 relay: false,
6764 initial_peers_config: InitialPeersConfig {
6765 first: false,
6766 addrs: vec![],
6767 network_contacts_url: vec![],
6768 local: false,
6769 ignore_cache: false,
6770 bootstrap_cache_dir: None,
6771 },
6772 listen_addr: None,
6773 log_dir_path: PathBuf::from("/var/log/antnode/antnode1"),
6774 log_format: None,
6775 max_archived_log_files: None,
6776 max_log_files: None,
6777 metrics_port: None,
6778 network_id: None,
6779 node_ip: None,
6780 node_port: None,
6781 number: 1,
6782 peer_id: Some(PeerId::from_str(
6783 "12D3KooWS2tpXGGTmg2AHFiDh57yPQnat49YHnyqoggzXZWpqkCR",
6784 )?),
6785 pid: Some(1000),
6786 rewards_address: RewardsAddress::from_str(
6787 "0x03B770D9cD32077cC0bF330c13C114a87643B124",
6788 )?,
6789 reward_balance: Some(AttoTokens::zero()),
6790 rpc_socket_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8081),
6791 antnode_path: current_node_bin.to_path_buf(),
6792 schema_version: NODE_SERVICE_DATA_SCHEMA_LATEST,
6793 service_name: "antnode1".to_string(),
6794 status: ServiceStatus::Running,
6795 no_upnp: false,
6796 user: Some("ant".to_string()),
6797 user_mode: false,
6798 version: current_version.to_string(),
6799 write_older_cache_files: false,
6800 };
6801 let service_data = Arc::new(RwLock::new(service_data));
6802 let service = NodeService::new(Arc::clone(&service_data), Box::new(mock_rpc_client));
6803
6804 let mut service_manager = ServiceManager::new(
6805 service,
6806 Box::new(mock_service_control),
6807 VerbosityLevel::Normal,
6808 );
6809
6810 service_manager
6811 .upgrade(UpgradeOptions {
6812 auto_restart: false,
6813 env_variables: None,
6814 force: false,
6815 start_service: true,
6816 target_bin_path: target_node_bin.to_path_buf(),
6817 target_version: Version::parse(target_version).unwrap(),
6818 })
6819 .await?;
6820
6821 let service_data = service_data.read().await;
6822 assert!(service_data.alpha);
6823
6824 Ok(())
6825 }
6826}