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