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