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