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