ant_node_manager/cmd/
mod.rs1pub mod daemon;
10pub mod local;
11pub mod nat_detection;
12pub mod node;
13
14use crate::{
15 helpers::{download_and_extract_release, get_bin_version},
16 print_banner, VerbosityLevel,
17};
18use ant_releases::{AntReleaseRepoActions, ReleaseType};
19use ant_service_management::UpgradeResult;
20use color_eyre::{eyre::eyre, Result};
21use colored::Colorize;
22use semver::Version;
23use std::{
24 path::PathBuf,
25 process::{Command, Stdio},
26};
27
28pub async fn download_and_get_upgrade_bin_path(
29 custom_bin_path: Option<PathBuf>,
30 release_type: ReleaseType,
31 url: Option<String>,
32 version: Option<String>,
33 verbosity: VerbosityLevel,
34) -> Result<(PathBuf, Version)> {
35 if let Some(path) = custom_bin_path {
36 debug!(
37 "Using the supplied custom binary at {}",
38 path.to_string_lossy()
39 );
40 if verbosity != VerbosityLevel::Minimal {
41 println!(
42 "Using the supplied custom binary at {}",
43 path.to_string_lossy()
44 );
45 }
46 let bin_version = get_bin_version(&path)?;
47 return Ok((path, bin_version.parse()?));
48 }
49
50 let release_repo = <dyn AntReleaseRepoActions>::default_config();
51 if let Some(version) = version {
52 debug!("Downloading provided version {version} of {release_type}");
53 let (upgrade_bin_path, version) = download_and_extract_release(
54 release_type,
55 None,
56 Some(version),
57 &*release_repo,
58 verbosity,
59 None,
60 )
61 .await?;
62 Ok((upgrade_bin_path, Version::parse(&version)?))
63 } else if let Some(url) = url {
64 debug!("Downloading {release_type} from url: {url}");
65 let (upgrade_bin_path, version) = download_and_extract_release(
66 release_type,
67 Some(url),
68 None,
69 &*release_repo,
70 verbosity,
71 None,
72 )
73 .await?;
74 Ok((upgrade_bin_path, Version::parse(&version)?))
75 } else {
76 if verbosity != VerbosityLevel::Minimal {
77 println!("Retrieving latest version of {release_type}...");
78 }
79 debug!("Retrieving latest version of {release_type}...");
80 let latest_version = release_repo.get_latest_version(&release_type).await?;
81 if verbosity != VerbosityLevel::Minimal {
82 println!("Latest version is {latest_version}");
83 }
84 debug!("Download latest version {latest_version} of {release_type}");
85
86 let (upgrade_bin_path, _) = download_and_extract_release(
87 release_type,
88 None,
89 Some(latest_version.to_string()),
90 &*release_repo,
91 verbosity,
92 None,
93 )
94 .await?;
95 Ok((upgrade_bin_path, latest_version))
96 }
97}
98
99pub fn print_upgrade_summary(upgrade_summary: Vec<(String, UpgradeResult)>) {
100 println!("Upgrade summary:");
101 for (service_name, upgrade_result) in upgrade_summary {
102 match upgrade_result {
103 UpgradeResult::NotRequired => {
104 println!("- {service_name} did not require an upgrade");
105 }
106 UpgradeResult::Upgraded(previous_version, new_version) => {
107 println!(
108 "{} {} upgraded from {previous_version} to {new_version}",
109 "✓".green(),
110 service_name
111 );
112 }
113 UpgradeResult::UpgradedButNotStarted(previous_version, new_version, _) => {
114 println!(
115 "{} {} was upgraded from {previous_version} to {new_version} but it did not start",
116 "✕".red(),
117 service_name
118 );
119 }
120 UpgradeResult::Forced(previous_version, target_version) => {
121 println!(
122 "{} Forced {} version change from {previous_version} to {target_version}.",
123 "✓".green(),
124 service_name
125 );
126 }
127 UpgradeResult::Error(msg) => {
128 println!("{} {} was not upgraded: {}", "✕".red(), service_name, msg);
129 }
130 }
131 }
132}
133
134pub async fn get_bin_path(
135 build: bool,
136 path: Option<PathBuf>,
137 release_type: ReleaseType,
138 version: Option<String>,
139 release_repo: &dyn AntReleaseRepoActions,
140 verbosity: VerbosityLevel,
141) -> Result<PathBuf> {
142 if build {
143 debug!("Obtaining bin path for {release_type:?} by building");
144 let target_dir = build_binary(&release_type)?;
145 Ok(target_dir.join(release_type.to_string()))
146 } else if let Some(path) = path {
147 debug!("Using the supplied custom binary for {release_type:?}: {path:?}");
148 Ok(path)
149 } else {
150 debug!("Downloading {release_type:?} binary with version {version:?}");
151 let (download_path, _) = download_and_extract_release(
152 release_type,
153 None,
154 version,
155 release_repo,
156 verbosity,
157 None,
158 )
159 .await?;
160 Ok(download_path)
161 }
162}
163
164fn build_binary(bin_type: &ReleaseType) -> Result<PathBuf> {
166 debug!("Building {bin_type} binary");
167 let mut args = vec!["build", "--release"];
168 let bin_name = bin_type.to_string();
169 args.push("--bin");
170 args.push(&bin_name);
171
172 if cfg!(feature = "chaos") {
174 println!("*** Building testnet with CHAOS enabled. Watch out. ***");
175 args.push("--features");
176 args.push("chaos");
177 }
178 if cfg!(feature = "statemap") {
179 args.extend(["--features", "statemap"]);
180 }
181 if cfg!(feature = "otlp") {
182 args.extend(["--features", "otlp"]);
183 }
184 if cfg!(feature = "websockets") {
185 args.extend(["--features", "websockets"]);
186 }
187 if cfg!(feature = "open-metrics") {
188 args.extend(["--features", "open-metrics"]);
189 }
190
191 print_banner(&format!("Building {bin_name} binary"));
192
193 let mut target_dir = PathBuf::new();
194 let mut build_result = Command::new("cargo");
195 let _ = build_result.args(args.clone());
196
197 if let Ok(val) = std::env::var("CARGO_TARGET_DIR") {
198 let _ = build_result.env("CARGO_TARGET_DIR", val.clone());
199 target_dir.push(val);
200 } else {
201 target_dir.push("target");
202 }
203 let target_dir = target_dir.join("release");
204
205 let build_result = build_result
206 .stdout(Stdio::inherit())
207 .stderr(Stdio::inherit())
208 .output()?;
209
210 if !build_result.status.success() {
211 error!("Failed to build binaries {bin_name}");
212 return Err(eyre!("Failed to build binaries"));
213 }
214
215 Ok(target_dir)
216}