This repository has been archived by the owner on Dec 21, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
65b1a5c
commit 8d0ab65
Showing
19 changed files
with
429 additions
and
150 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,69 +2,59 @@ pub mod database; | |
|
||
use global_error::prelude::*; | ||
use rivet_api::{apis, models}; | ||
use serde::{Deserialize, Serialize}; | ||
use std::{collections::HashMap, fs::File, io::Write, path::PathBuf, str::FromStr}; | ||
use tempfile::NamedTempFile; | ||
use tokio::{fs, process::Command, signal}; | ||
|
||
use crate::{ | ||
config, | ||
util::{cmd::shell_cmd, task::TaskCtx}, | ||
Ctx, | ||
}; | ||
|
||
const DEFAULT_OPENGB_DOCKER_TAG: &'static str = "ghcr.io/rivet-gg/opengb/v0.1.2"; | ||
pub struct OpenGbCommandOpts { | ||
pub opengb_target: OpenGbTarget, | ||
pub args: Vec<String>, | ||
pub env: HashMap<String, String>, | ||
pub cwd: PathBuf, | ||
} | ||
|
||
#[derive(PartialEq)] | ||
pub enum OpenGbTarget { | ||
#[derive(PartialEq, Serialize, Deserialize, Clone)] | ||
pub enum OpenGbRuntime { | ||
Native, | ||
Docker, | ||
} | ||
|
||
impl Default for OpenGbTarget { | ||
impl Default for OpenGbRuntime { | ||
fn default() -> Self { | ||
Self::Docker | ||
} | ||
} | ||
impl FromStr for OpenGbTarget { | ||
type Err = GlobalError; | ||
|
||
fn from_str(s: &str) -> GlobalResult<Self> { | ||
match s { | ||
"native" => Ok(Self::Native), | ||
"docker" => Ok(Self::Docker), | ||
_ => bail!("unknown opengb target: {s}"), | ||
} | ||
} | ||
} | ||
pub async fn build_opengb_command(opts: OpenGbCommandOpts) -> GlobalResult<Command> { | ||
let (runtime, image_tag) = config::settings::try_read(|settings| { | ||
Ok(( | ||
settings.backend.opengb_runtime.clone(), | ||
settings.backend.opengb_docker_image.clone(), | ||
)) | ||
}) | ||
.await?; | ||
|
||
pub fn build_opengb_command(opts: OpenGbCommandOpts) -> GlobalResult<Command> { | ||
// Build command | ||
match opts.opengb_target { | ||
OpenGbTarget::Native => { | ||
match runtime { | ||
OpenGbRuntime::Native => { | ||
let mut cmd = shell_cmd("opengb"); | ||
cmd.args(opts.args); | ||
cmd.envs(opts.env); | ||
cmd.current_dir(opts.cwd); | ||
Ok(cmd) | ||
} | ||
OpenGbTarget::Docker => { | ||
let image_tag = std::env::var("RIVET_OPENGB_DOCKER_IMAGE") | ||
.ok() | ||
.unwrap_or_else(|| DEFAULT_OPENGB_DOCKER_TAG.to_string()); | ||
OpenGbRuntime::Docker => { | ||
let image_tag = image_tag.unwrap_or_else(|| DEFAULT_OPENGB_DOCKER_TAG.to_string()); | ||
|
||
// Build env file | ||
let mut env_file = NamedTempFile::new().expect("Failed to create temp file"); | ||
for (k, v) in std::env::vars() { | ||
writeln!(env_file, "{k}={v}")?; | ||
} | ||
if std::env::var("DATABASE_URL").is_err() { | ||
writeln!(env_file, "DATABASE_URL=postgres://postgres:[email protected]:5432/postgres?sslmode=disable")?; | ||
} | ||
for (k, v) in opts.env { | ||
writeln!(env_file, "{k}={v}")?; | ||
} | ||
|
@@ -88,13 +78,13 @@ pub fn build_opengb_command(opts: OpenGbCommandOpts) -> GlobalResult<Command> { | |
} | ||
|
||
pub async fn run_opengb_command(task: TaskCtx, opts: OpenGbCommandOpts) -> GlobalResult<i32> { | ||
let cmd = build_opengb_command(opts)?; | ||
let cmd = build_opengb_command(opts).await?; | ||
let exit_code = task.spawn_cmd(cmd).await?; | ||
Ok(exit_code.code().unwrap_or(0)) | ||
} | ||
|
||
pub async fn spawn_opengb_command(opts: OpenGbCommandOpts) -> GlobalResult<u32> { | ||
let child = build_opengb_command(opts)?.spawn()?; | ||
let child = build_opengb_command(opts).await?.spawn()?; | ||
Ok(unwrap!(child.id(), "child already exited")) | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
pub mod global; | ||
pub mod settings; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
use global_error::prelude::*; | ||
use serde::{Deserialize, Serialize}; | ||
use std::collections::HashMap; | ||
use tokio::sync::{Mutex, OnceCell}; | ||
|
||
use crate::{ | ||
backend::OpenGbRuntime, | ||
paths, | ||
util::docker::{build::DockerBuildMethod, BuildCompression, BuildKind}, | ||
}; | ||
|
||
#[derive(Default, Clone, Serialize, Deserialize)] | ||
pub struct Settings { | ||
#[serde(default)] | ||
pub backend: BackendConfig, | ||
#[serde(default)] | ||
pub game_server: GameServerConfig, | ||
#[serde(default)] | ||
pub net: NetConfig, | ||
} | ||
|
||
#[derive(Default, Clone, Serialize, Deserialize)] | ||
pub struct BackendConfig { | ||
/// Env vars to pass to all OpenGB commands. | ||
#[serde(default)] | ||
pub command_environment: HashMap<String, String>, | ||
#[serde(default)] | ||
pub opengb_runtime: OpenGbRuntime, | ||
#[serde(default)] | ||
pub opengb_docker_image: Option<String>, | ||
|
||
#[serde(default)] | ||
pub sdk: BackendSdkConfig, | ||
#[serde(default)] | ||
pub dev: BackendDevConfig, | ||
#[serde(default)] | ||
pub deploy: BackendDeployConfig, | ||
} | ||
|
||
#[derive(Default, Clone, Serialize, Deserialize)] | ||
pub struct BackendSdkConfig { | ||
/// Env vars to pass to the deploy OpenGB commands. | ||
#[serde(default)] | ||
pub command_environment: HashMap<String, String>, | ||
#[serde(default)] | ||
pub path: Option<String>, | ||
} | ||
|
||
#[derive(Default, Clone, Serialize, Deserialize)] | ||
pub struct BackendDevConfig { | ||
/// Env vars to pass to the deploy OpenGB commands. | ||
#[serde(default)] | ||
pub command_environment: HashMap<String, String>, | ||
} | ||
|
||
#[derive(Default, Clone, Serialize, Deserialize)] | ||
pub struct BackendDeployConfig { | ||
/// Env vars to pass to the deploy OpenGB commands. | ||
#[serde(default)] | ||
pub command_environment: HashMap<String, String>, | ||
} | ||
|
||
#[derive(Default, Clone, Serialize, Deserialize)] | ||
pub struct GameServerConfig { | ||
#[serde(default)] | ||
pub deploy: GameServerDeployConfig, | ||
} | ||
|
||
#[derive(Default, Clone, Serialize, Deserialize)] | ||
pub struct GameServerDeployConfig { | ||
#[serde(default)] | ||
pub dockerfile_path: Option<String>, | ||
#[serde(default)] | ||
pub docker_image: Option<String>, | ||
#[serde(default)] | ||
pub build_args: Option<HashMap<String, String>>, | ||
#[serde(default)] | ||
pub allow_root: bool, | ||
#[serde(default)] | ||
pub build_method: DockerBuildMethod, | ||
#[serde(default)] | ||
pub build_kind: BuildKind, | ||
// Default value depends on build_kind | ||
#[serde(default)] | ||
pub build_compression: Option<BuildCompression>, | ||
} | ||
|
||
#[derive(Default, Clone, Serialize, Deserialize)] | ||
pub struct NetConfig { | ||
#[serde(default)] | ||
pub disable_upload_multipart: bool, | ||
} | ||
|
||
static SINGLETON: OnceCell<Mutex<Settings>> = OnceCell::const_new(); | ||
|
||
async fn read() -> GlobalResult<&'static Mutex<Settings>> { | ||
let config = SINGLETON | ||
.get_or_try_init::<GlobalError, _, _>(|| async { | ||
let mut config_builder = | ||
config::ConfigBuilder::<config::builder::AsyncState>::default(); | ||
|
||
if paths::user_settings_config_file()?.exists() { | ||
config_builder = config_builder | ||
.add_source(config::File::from(paths::user_settings_config_file()?)); | ||
} | ||
if paths::project_settings_config_file()?.exists() { | ||
config_builder = config_builder | ||
.add_source(config::File::from(paths::project_settings_config_file()?)); | ||
} | ||
|
||
let config = unwrap!(config_builder.build().await, "find config"); | ||
let config_deserialized = | ||
unwrap!(config.try_deserialize::<Settings>(), "deserialize config"); | ||
|
||
Result::Ok(Mutex::new(config_deserialized)) | ||
}) | ||
.await?; | ||
Ok(config) | ||
} | ||
|
||
pub async fn try_read<F: FnOnce(&Settings) -> GlobalResult<T>, T>(cb: F) -> GlobalResult<T> { | ||
let singleton = read().await?; | ||
let mut lock = singleton.lock().await; | ||
|
||
// Fetch value | ||
let value = cb(&mut *lock)?; | ||
|
||
Ok(value) | ||
} |
Oops, something went wrong.