From 240ae19f90d8f96b6335b6afd3829d13fafbda26 Mon Sep 17 00:00:00 2001 From: Nathan Flurry Date: Sun, 21 Jul 2024 12:15:59 -0700 Subject: [PATCH] chore: check system requirements --- .../src/tasks/check_requirements.rs | 28 ------ .../src/tasks/check_system_requirements.rs | 95 +++++++++++++++++++ rivet-toolchain/src/tasks/mod.rs | 2 + 3 files changed, 97 insertions(+), 28 deletions(-) delete mode 100644 rivet-toolchain/src/tasks/check_requirements.rs create mode 100644 rivet-toolchain/src/tasks/check_system_requirements.rs diff --git a/rivet-toolchain/src/tasks/check_requirements.rs b/rivet-toolchain/src/tasks/check_requirements.rs deleted file mode 100644 index 583dda0c..00000000 --- a/rivet-toolchain/src/tasks/check_requirements.rs +++ /dev/null @@ -1,28 +0,0 @@ -use global_error::prelude::*; -use serde::{Deserialize, Serialize}; - -use crate::util::task::TaskCtx; - -#[derive(Deserialize)] -pub struct Input { - path: String, -} - -#[derive(Serialize)] -pub struct Output {} - -pub struct Task; - -impl super::Task for Task { - type Input = Input; - type Output = Output; - - fn name() -> &'static str { - "check_requirements" - } - - async fn run(_task: TaskCtx, input: Self::Input) -> GlobalResult { - // TODO: - Ok(Output {}) - } -} diff --git a/rivet-toolchain/src/tasks/check_system_requirements.rs b/rivet-toolchain/src/tasks/check_system_requirements.rs new file mode 100644 index 00000000..11b41203 --- /dev/null +++ b/rivet-toolchain/src/tasks/check_system_requirements.rs @@ -0,0 +1,95 @@ +use global_error::prelude::*; +use serde::{Deserialize, Serialize}; +use std::time::Duration; + +use crate::util::{cmd::shell_cmd, task::TaskCtx}; + +#[derive(Deserialize)] +pub struct Input {} + +#[derive(Serialize)] +pub struct Output { + errors: Vec, +} + +#[derive(Serialize)] +pub struct RequirementError { + title: String, + body: String, + docs_url: Option, +} + +pub struct Task; + +impl super::Task for Task { + type Input = Input; + type Output = Output; + + fn name() -> &'static str { + "check_system_requirements" + } + + async fn run(_task: TaskCtx, _input: Self::Input) -> GlobalResult { + let mut errors = Vec::new(); + + // Docker + match tokio::time::timeout( + Duration::from_secs(5), + shell_cmd("docker").arg("info").kill_on_drop(true).output(), + ) + .await + { + Ok(Ok(output)) => { + if !output.status.success() { + if output.status.code() == Some(127) { + errors.push(errors::docker_not_found()); + } else { + errors.push(RequirementError { + title: "Docker Failed".into(), + body: format!( + "Exit code: {}\n\n{}", + output + .status + .code() + .map_or_else(|| "?".to_string(), |x| x.to_string()), + String::from_utf8_lossy(&output.stderr).to_string() + ), + docs_url: None, + }); + } + } + } + Ok(Err(err)) if err.kind() == std::io::ErrorKind::NotFound => { + errors.push(errors::docker_not_found()) + } + Ok(Err(err)) => { + errors.push(RequirementError { + title: "Docker Command Error".into(), + body: err.to_string(), + docs_url: Some("https://docs.docker.com/get-docker/".into()), + }); + } + Err(_) => { + errors.push(RequirementError { + title: "Docker Command Timed Out".into(), + body: "Docker may be paused. Try restarting Docker.".into(), + docs_url: None, + }); + } + } + + Ok(Output { errors }) + } +} + +mod errors { + use super::RequirementError; + + pub fn docker_not_found() -> RequirementError { + RequirementError { + title: "Install Docker".into(), + body: "Docker is required to build & run the game server & backend.".into(), + docs_url: Some("https://docs.docker.com/get-docker/".into()), + } + } +} diff --git a/rivet-toolchain/src/tasks/mod.rs b/rivet-toolchain/src/tasks/mod.rs index a2c4df1e..67ea7989 100644 --- a/rivet-toolchain/src/tasks/mod.rs +++ b/rivet-toolchain/src/tasks/mod.rs @@ -2,6 +2,7 @@ pub mod backend_choose_local_port; pub mod backend_dev; pub mod backend_sdk_gen; pub mod check_login_state; +pub mod check_system_requirements; pub mod deploy; pub mod exec_command; pub mod get_bootstrap_data; @@ -77,6 +78,7 @@ gen_run_task!( backend_dev::Task, backend_sdk_gen::Task, check_login_state::Task, + check_system_requirements::Task, deploy::Task, exec_command::Task, get_bootstrap_data::Task,