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