mod cli_tools;
mod dns_resolver;
mod docker_socket;
mod hosts_alias;
pub use cli_tools::CliTools;
pub use dns_resolver::DnsResolver;
pub use docker_socket::DockerSocket;
pub use hosts_alias::HostsAlias;
use anyhow::Context as _;
use arcbox_helper::client::{Client, ClientError};
#[async_trait::async_trait]
pub trait SetupTask: Send + Sync {
fn name(&self) -> &'static str;
fn is_satisfied(&self) -> bool;
async fn apply(&self, client: &Client) -> Result<(), ClientError>;
}
pub async fn run_required(task: &dyn SetupTask) -> anyhow::Result<()> {
if task.is_satisfied() {
return Ok(());
}
let client = Client::connect()
.await
.with_context(|| format!("{} requires a compatible arcbox-helper", task.name()))?;
task.apply(&client)
.await
.with_context(|| format!("failed to configure {}", task.name()))?;
anyhow::ensure!(
task.is_satisfied(),
"{} was not satisfied after helper configuration",
task.name()
);
tracing::info!(task = task.name(), "configured");
Ok(())
}
pub async fn run(tasks: &[&dyn SetupTask]) {
let client = match Client::connect().await {
Ok(c) => c,
Err(ClientError::UnrecognizedVersion(version)) => {
tracing::warn!(
version = %version,
"arcbox-helper returned an unrecognized version; run 'sudo abctl _install --no-daemon --no-shell' to replace it"
);
return;
}
Err(ClientError::IncompatibleVersion {
installed,
required,
}) => {
tracing::warn!(
installed = %installed,
required,
"arcbox-helper is incompatible; run 'sudo abctl _install --no-daemon --no-shell' to replace it"
);
return;
}
Err(e) => {
tracing::debug!(
error = %e,
"arcbox-helper unavailable, skipping self-setup"
);
return;
}
};
for task in tasks {
let name = task.name();
if task.is_satisfied() {
tracing::debug!(task = name, "already satisfied");
continue;
}
match task.apply(&client).await {
Ok(()) => tracing::info!(task = name, "configured"),
Err(e) => tracing::warn!(
task = name,
error = %e,
"failed (run 'sudo abctl _install --no-daemon --no-shell' to fix)"
),
}
}
}