use crate::args::{username_password_argument, version_argument};
use crate::constants::WILDFLY_ADMIN_CONTAINER;
use crate::podman::get_instance;
use crate::progress::Progress;
use crate::wildfly::ManagementClient;
use anyhow::{Context, anyhow};
use clap::ArgMatches;
use fs::{File, create_dir_all};
use futures::executor::block_on;
use std::env::temp_dir;
use std::fs;
use std::io::Write;
use std::path::PathBuf;
use tokio::process::Command;
use which::which;
use wildfly_container_versions::WildFlyContainer;
pub fn cli(matches: &ArgMatches) -> anyhow::Result<()> {
which("java").with_context(|| "podman not found")?;
let management_client = if let Some(name) = matches.get_one::<String>("name") {
let mut v = vec![];
let wildfly_containers = if let Some(wildfly_container) =
matches.get_one::<WildFlyContainer>("wildfly-version")
{
v.push(wildfly_container.clone());
Some(&v)
} else {
None
};
let instance = block_on(get_instance(wildfly_containers, Some(name)))?;
ManagementClient::from_container_instance(&instance)
} else {
let wildfly_container = &version_argument(matches);
ManagementClient::custom_port(
wildfly_container,
*matches
.get_one::<u16>("management")
.unwrap_or(&wildfly_container.management_port()),
)
};
let (username, password) = username_password_argument(matches);
let parameters = matches
.get_many::<String>("cli-parameters")
.unwrap_or_default()
.map(|p| p.clone())
.collect::<Vec<_>>();
let temp_dir = temp_dir().join(format!(
"{}-cli-{}",
WILDFLY_ADMIN_CONTAINER, management_client.wildfly_container.identifier
));
create_dir_all(&temp_dir)?;
block_on(connect_to_cli(
&management_client,
&temp_dir,
username,
password,
parameters,
))
}
async fn connect_to_cli(
management_client: &ManagementClient,
cli_dir: &PathBuf,
username: &str,
password: &str,
parameters: Vec<String>,
) -> anyhow::Result<()> {
let progress = Progress::new(
&management_client.wildfly_container.short_version,
&management_client.wildfly_container.image_name(),
);
let cli_jar = cli_dir.join("cli.jar");
let cli_config = cli_dir.join("cli.xml");
progress.show_progress("Downloading CLI jar and config...");
let (jar_result, config_result) = futures::join!(
download_file(management_client.cli_jar_url.as_str(), &cli_jar),
download_file(management_client.cli_config_url.as_str(), &cli_config)
);
jar_result?;
config_result?;
progress.finish_no_output(None);
let output = Command::new("java")
.arg(format!(
"-Djboss.cli.config={}",
cli_config.as_os_str().to_str().unwrap()
))
.arg("-jar")
.arg(cli_jar)
.arg(format!("--user={}", username))
.arg(format!("--password={}", password))
.arg(format!(
"--controller=localhost:{}",
management_client.management_port
))
.arg("--connect")
.args(parameters.clone())
.spawn()?
.wait_with_output()
.await?;
if output.status.success() {
Ok(())
} else {
Err(anyhow!(
"CLI failed with exit code: {}",
output.status.code().unwrap()
))
}
}
async fn download_file(url: &str, path: &PathBuf) -> anyhow::Result<()> {
if path.exists() {
Ok(())
} else {
let response = reqwest::get(url).await?;
if response.status().is_success() {
let mut file = File::create(&path)?;
let content = response.bytes().await?;
file.write_all(&content)?;
Ok(())
} else {
Err(anyhow!("Failed to download: {}", response.status()))
}
}
}