Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: provide autonomi-launcher binary #1663

Merged
merged 2 commits into from
May 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 16 additions & 1 deletion Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ build-release-artifacts arch:
cross build --release --target $arch --bin faucet --features=distribution
cross build --release --target $arch --bin safenode_rpc_client
cross build --release --target $arch --bin node-launchpad
cross build --release --target $arch --bin autonomi-launcher
else
cargo build --release --features="network-contacts,distribution" --target $arch --bin safe
cargo build --release --features=network-contacts --target $arch --bin safenode
Expand All @@ -128,6 +129,7 @@ build-release-artifacts arch:
cargo build --release --target $arch --bin faucet --features=distribution
cargo build --release --target $arch --bin safenode_rpc_client
cargo build --release --target $arch --bin node-launchpad
cargo build --release --target $arch --bin autonomi-launcher
fi

find target/$arch/release -maxdepth 1 -type f -exec cp '{}' artifacts \;
Expand Down Expand Up @@ -172,7 +174,14 @@ package-release-assets bin version="":
bin="{{bin}}"

supported_bins=(\
"safe" "safenode" "safenode-manager" "safenodemand" "faucet" "safenode_rpc_client" "node-launchpad")
"safe" \
"safenode" \
"safenode-manager" \
"safenodemand" \
"faucet" \
"safenode_rpc_client" \
"node-launchpad" \
"autonomi-launcher")
crate_dir_name=""

# In the case of the node manager, the actual name of the crate is `sn-node-manager`, but the
Expand Down Expand Up @@ -200,6 +209,9 @@ package-release-assets bin version="":
node-launchpad)
crate_dir_name="sn_node_launchpad"
;;
autonomi-launcher)
crate_dir_name="sn_node_launchpad"
;;
*)
echo "The $bin binary is not supported"
exit 1
Expand Down Expand Up @@ -331,6 +343,9 @@ upload-release-assets-to-s3 bin_name:
node-launchpad)
bucket="sn-node-launchpad"
;;
autonomi-launcher-launchpad)
bucket="sn-node-launchpad"
;;
*)
echo "The {{bin_name}} binary is not supported"
exit 1
Expand Down
15 changes: 11 additions & 4 deletions sn_node_launchpad/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ build = "build.rs"

[[bin]]
name = "node-launchpad"
path = "src/main.rs"
path = "src/bin/tui/main.rs"

[[bin]]
name = "autonomi-launcher"
path = "src/bin/launcher/main.rs"

[dependencies]
sn_peers_acquisition = { verison = "0.2.10", path = "../sn_peers_acquisition" }
sn_service_management = { verison = "0.2.4", path = "../sn_service_management" }
better-panic = "0.3.0"
clap = { version = "4.4.5", features = [
"derive",
Expand All @@ -31,6 +33,7 @@ config = "0.14.0"
crossterm = { version = "0.27.0", features = ["serde", "event-stream"] }
derive_deref = "1.1.1"
directories = "5.0.1"
dirs-next = "~2.0.0"
futures = "0.3.28"
human-panic = "1.2.0"
json5 = "0.4.1"
Expand All @@ -40,9 +43,12 @@ log = "0.4.20"
pretty_assertions = "1.4.0"
ratatui = { version = "0.26.0", features = ["serde", "macros"] }
serde = { version = "1.0.188", features = ["derive"] }
sn-node-manager = { verison = "0.7.4", path = "../sn_node_manager" }
serde_json = "1.0.107"
signal-hook = "0.3.17"
sn-node-manager = { version = "0.7.4", path = "../sn_node_manager" }
sn_peers_acquisition = { version = "0.2.10", path = "../sn_peers_acquisition" }
sn-releases = "0.2.1"
sn_service_management = { version = "0.2.4", path = "../sn_service_management" }
strip-ansi-escapes = "0.2.0"
strum = { version = "0.26.1", features = ["derive"] }
tokio = { version = "1.32.0", features = ["full"] }
Expand All @@ -51,6 +57,7 @@ tracing = "0.1.37"
tracing-error = "0.2.0"
tracing-subscriber = { version = "0.3.17", features = ["env-filter", "serde"] }
tui-input = "0.8.0"
which = "6.0.1"

[build-dependencies]
vergen = { version = "8.2.6", features = ["build", "git", "gitoxide", "cargo"] }
206 changes: 206 additions & 0 deletions sn_node_launchpad/src/bin/launcher/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
// Copyright 2024 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under The General Public License (GPL), version 3.
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. Please review the Licences for the specific language governing
// permissions and limitations relating to use of the SAFE Network Software.

use clap::Parser;
use color_eyre::{eyre::eyre, eyre::Result};

use sn_node_manager::{
helpers::{create_temp_dir, download_and_extract_release},
VerbosityLevel,
};
use sn_releases::{ReleaseType, SafeReleaseRepoActions};
use std::{
path::{Path, PathBuf},
process::Command,
};
use which::which;

#[derive(Debug)]
enum TerminalType {
Alacritty(PathBuf),
Gnome(PathBuf),
ITerm2(PathBuf),
Kitty(PathBuf),
Konsole(PathBuf),
MacOS(PathBuf),
WindowsCmd(PathBuf),
WindowsPowershell(PathBuf),
WindowsTerminal(PathBuf),
Xterm(PathBuf),
}

fn detect_terminal() -> Result<TerminalType> {
if cfg!(target_os = "windows") {
if let Ok(path) = which("wt.exe") {
Ok(TerminalType::WindowsTerminal(path))
} else if let Ok(path) = which("powershell.exe") {
Ok(TerminalType::WindowsPowershell(path))
} else if let Ok(path) = which("cmd.exe") {
Ok(TerminalType::WindowsCmd(path))
} else {
Err(eyre!("Could not find suitable terminal on Windows"))
}
} else if cfg!(target_os = "macos") {
if which("iTerm.app").is_ok() {
Ok(TerminalType::ITerm2(PathBuf::from("osascript")))
} else {
Ok(TerminalType::MacOS(PathBuf::from("osascript")))
}
} else {
get_linux_terminal()
}
}

fn get_linux_terminal() -> Result<TerminalType> {
match std::env::var("TERM") {
Ok(val) => {
if let Ok(path) = which(val.clone()) {
match val.as_str() {
"alacritty" => Ok(TerminalType::Alacritty(path)),
"gnome" => Ok(TerminalType::Gnome(path)),
"kitty" => Ok(TerminalType::Kitty(path)),
"konsole" => Ok(TerminalType::Konsole(path)),
"xterm" => Ok(TerminalType::Xterm(path)),
"xterm-256color" => Ok(TerminalType::Xterm(path)),
_ => Err(eyre!("Terminal '{val}' is not supported")),
}
} else {
try_available_linux_terminals()
}
}
Err(_) => try_available_linux_terminals(),
}
}

fn try_available_linux_terminals() -> Result<TerminalType> {
if let Ok(path) = which("alacritty") {
Ok(TerminalType::Alacritty(path))
} else if let Ok(path) = which("gnome-terminal") {
Ok(TerminalType::Gnome(path))
} else if let Ok(path) = which("kitty") {
Ok(TerminalType::Kitty(path))
} else if let Ok(path) = which("konsole") {
Ok(TerminalType::Konsole(path))
} else if let Ok(path) = which("xterm") {
Ok(TerminalType::Xterm(path))
} else if let Ok(path) = which("xterm-256color") {
Ok(TerminalType::Xterm(path))
} else {
Err(eyre!("Could not find terminal on Linux"))
}
}

fn launch_terminal(terminal_type: &TerminalType, launchpad_path: &Path) -> Result<()> {
let launchpad_path = launchpad_path.to_string_lossy().to_string();
match terminal_type {
TerminalType::Kitty(path) | TerminalType::Konsole(path) | TerminalType::Xterm(path) => {
Command::new(path).arg("-e").arg(launchpad_path).spawn()?;
Ok(())
}
TerminalType::Alacritty(path) => {
Command::new(path)
.arg("--command")
.arg("sudo")
.arg("sh")
.arg("-c")
.arg(launchpad_path)
.spawn()?;
Ok(())
}
TerminalType::Gnome(path) => {
Command::new(path)
.arg("--")
.arg("sudo")
.arg(launchpad_path)
.spawn()?;
Ok(())
}
TerminalType::MacOS(path) => {
Command::new(path)
.arg("-e")
.arg(format!(
"tell application \"Terminal\" to do script \"sudo {}\"",
launchpad_path
))
.spawn()?;
Ok(())
}
TerminalType::ITerm2(path) => {
Command::new(path)
.arg("-e")
.arg(format!("tell application \"iTerm\" to create window with default profile command \"sudo {}\"", launchpad_path))
.spawn()?;
Ok(())
}
TerminalType::WindowsCmd(path)
| TerminalType::WindowsPowershell(path)
| TerminalType::WindowsTerminal(path) => {
Command::new(path).arg("/c").arg(launchpad_path).spawn()?;
Ok(())
}
}
}

#[derive(Parser, Debug)]
#[command(author, about)]
pub struct Cli {
#[arg(long)]
pub launchpad_path: Option<PathBuf>,
#[arg(long)]
pub launchpad_version: Option<String>,
}

#[tokio::main]
async fn main() -> Result<()> {
let args = Cli::parse();
let launchpad_path = if let Some(path) = args.launchpad_path {
path
} else {
let path = get_node_launchpad_path()?;
if path.exists() {
path
} else {
println!("Retrieving latest version of Node Launchpad...");
let release_repo = <dyn SafeReleaseRepoActions>::default_config();
let (bin_path, _) = download_and_extract_release(
ReleaseType::NodeLaunchpad,
None,
None,
&*release_repo,
VerbosityLevel::Normal,
Some(create_temp_dir()?),
)
.await?;

std::fs::copy(bin_path, path.clone())?;
path
}
};

let terminal_type = detect_terminal()?;
launch_terminal(&terminal_type, &launchpad_path)?;
Ok(())
}

#[cfg(target_os = "windows")]
fn get_node_launchpad_path() -> Result<PathBuf> {
let home_dir_path =
dirs_next::home_dir().ok_or_else(|| eyre!("Could not retrieve user's home directory"))?;
let safe_dir_path = home_dir_path.join("safe");
std::fs::create_dir_all(safe_dir_path.clone())?;
Ok(safe_dir_path.join("node-launchpad.exe"))
}

#[cfg(target_family = "unix")]
fn get_node_launchpad_path() -> Result<PathBuf> {
let home_dir_path =
dirs_next::home_dir().ok_or_else(|| eyre!("Could not retrieve user's home directory"))?;
let safe_dir_path = home_dir_path.join(".local").join("bin");
std::fs::create_dir_all(safe_dir_path.clone())?;
Ok(safe_dir_path.join("node-launchpad.exe"))
}
Loading
Loading