aboutsummaryrefslogtreecommitdiff
path: root/planetwars-server
diff options
context:
space:
mode:
Diffstat (limited to 'planetwars-server')
-rw-r--r--planetwars-server/src/lib.rs28
-rw-r--r--planetwars-server/src/modules/bots.rs5
-rw-r--r--planetwars-server/src/modules/matches.rs25
-rw-r--r--planetwars-server/src/routes/bots.rs13
-rw-r--r--planetwars-server/src/routes/demo.rs2
-rw-r--r--planetwars-server/src/routes/matches.rs9
6 files changed, 45 insertions, 37 deletions
diff --git a/planetwars-server/src/lib.rs b/planetwars-server/src/lib.rs
index d9f5e8e..7e14add 100644
--- a/planetwars-server/src/lib.rs
+++ b/planetwars-server/src/lib.rs
@@ -29,9 +29,6 @@ use axum::{
};
// TODO: make these configurable
-const BOTS_DIR: &str = "./data/bots";
-const MATCHES_DIR: &str = "./data/matches";
-const MAPS_DIR: &str = "./data/maps";
const SIMPLEBOT_PATH: &str = "../simplebot/simplebot.py";
type ConnectionPool = bb8::Pool<DieselConnectionManager<PgConnection>>;
@@ -39,9 +36,13 @@ type ConnectionPool = bb8::Pool<DieselConnectionManager<PgConnection>>;
pub struct GlobalConfig {
pub python_runner_image: String,
pub container_registry_url: String,
+
+ pub bots_directory: String,
+ pub match_logs_directory: String,
+ pub maps_directory: String,
}
-pub async fn seed_simplebot(pool: &ConnectionPool) {
+pub async fn seed_simplebot(config: &GlobalConfig, pool: &ConnectionPool) {
let conn = pool.get().await.expect("could not get database connection");
// This transaction is expected to fail when simplebot already exists.
let _res = conn.transaction::<(), diesel::result::Error, _>(|| {
@@ -57,7 +58,7 @@ pub async fn seed_simplebot(pool: &ConnectionPool) {
let simplebot_code =
std::fs::read_to_string(SIMPLEBOT_PATH).expect("could not read simplebot code");
- modules::bots::save_code_string(&simplebot_code, Some(simplebot.id), &conn)?;
+ modules::bots::save_code_string(&simplebot_code, Some(simplebot.id), &conn, config)?;
println!("initialized simplebot");
@@ -67,10 +68,10 @@ pub async fn seed_simplebot(pool: &ConnectionPool) {
pub type DbPool = Pool<DieselConnectionManager<PgConnection>>;
-pub async fn prepare_db(database_url: &str) -> DbPool {
+pub async fn prepare_db(database_url: &str, config: &GlobalConfig) -> DbPool {
let manager = DieselConnectionManager::<PgConnection>::new(database_url);
let pool = bb8::Pool::builder().build(manager).await.unwrap();
- seed_simplebot(&pool).await;
+ seed_simplebot(&config, &pool).await;
pool
}
@@ -124,20 +125,25 @@ async fn run_registry(db_pool: DbPool) {
pub async fn run_app() {
let configuration = get_config().unwrap();
- let db_pool = prepare_db(&configuration.database_url).await;
- let runner_config = Arc::new(GlobalConfig {
+ let global_config = Arc::new(GlobalConfig {
python_runner_image: "python:3.10-slim-buster".to_string(),
container_registry_url: "localhost:9001".to_string(),
+
+ bots_directory: "./data/bots".to_string(),
+ match_logs_directory: "./data/matches".to_string(),
+ maps_directory: "./data/maps".to_string(),
});
- tokio::spawn(run_ranker(runner_config.clone(), db_pool.clone()));
+ let db_pool = prepare_db(&configuration.database_url, &global_config).await;
+
+ tokio::spawn(run_ranker(global_config.clone(), db_pool.clone()));
tokio::spawn(run_registry(db_pool.clone()));
let api_service = Router::new()
.nest("/api", api())
.layer(Extension(db_pool))
- .layer(Extension(runner_config))
+ .layer(Extension(global_config))
.into_make_service();
// TODO: put in config
diff --git a/planetwars-server/src/modules/bots.rs b/planetwars-server/src/modules/bots.rs
index b82ad41..5513539 100644
--- a/planetwars-server/src/modules/bots.rs
+++ b/planetwars-server/src/modules/bots.rs
@@ -2,17 +2,18 @@ use std::path::PathBuf;
use diesel::{PgConnection, QueryResult};
-use crate::{db, util::gen_alphanumeric, BOTS_DIR};
+use crate::{db, util::gen_alphanumeric, GlobalConfig};
/// Save a string containing bot code as a code bundle.
pub fn save_code_string(
bot_code: &str,
bot_id: Option<i32>,
conn: &PgConnection,
+ config: &GlobalConfig,
) -> QueryResult<db::bots::BotVersion> {
let bundle_name = gen_alphanumeric(16);
- let code_bundle_dir = PathBuf::from(BOTS_DIR).join(&bundle_name);
+ let code_bundle_dir = PathBuf::from(&config.bots_directory).join(&bundle_name);
std::fs::create_dir(&code_bundle_dir).unwrap();
std::fs::write(code_bundle_dir.join("bot.py"), bot_code).unwrap();
diff --git a/planetwars-server/src/modules/matches.rs b/planetwars-server/src/modules/matches.rs
index dd5e523..a1fe63d 100644
--- a/planetwars-server/src/modules/matches.rs
+++ b/planetwars-server/src/modules/matches.rs
@@ -11,13 +11,13 @@ use crate::{
matches::{MatchData, MatchResult},
},
util::gen_alphanumeric,
- ConnectionPool, GlobalConfig, BOTS_DIR, MAPS_DIR, MATCHES_DIR,
+ ConnectionPool, GlobalConfig,
};
pub struct RunMatch {
log_file_name: String,
players: Vec<MatchPlayer>,
- runner_config: Arc<GlobalConfig>,
+ config: Arc<GlobalConfig>,
}
pub enum MatchPlayer {
@@ -31,10 +31,10 @@ pub enum MatchPlayer {
}
impl RunMatch {
- pub fn from_players(runner_config: Arc<GlobalConfig>, players: Vec<MatchPlayer>) -> Self {
+ pub fn from_players(config: Arc<GlobalConfig>, players: Vec<MatchPlayer>) -> Self {
let log_file_name = format!("{}.log", gen_alphanumeric(16));
RunMatch {
- runner_config,
+ config,
log_file_name,
players,
}
@@ -42,16 +42,16 @@ impl RunMatch {
fn into_runner_config(self) -> runner::MatchConfig {
runner::MatchConfig {
- map_path: PathBuf::from(MAPS_DIR).join("hex.json"),
+ map_path: PathBuf::from(&self.config.maps_directory).join("hex.json"),
map_name: "hex".to_string(),
- log_path: PathBuf::from(MATCHES_DIR).join(&self.log_file_name),
+ log_path: PathBuf::from(&self.config.match_logs_directory).join(&self.log_file_name),
players: self
.players
.into_iter()
.map(|player| runner::MatchPlayer {
bot_spec: match player {
MatchPlayer::BotVersion { bot, version } => {
- bot_version_to_botspec(&self.runner_config, bot.as_ref(), &version)
+ bot_version_to_botspec(&self.config, bot.as_ref(), &version)
}
MatchPlayer::BotSpec { spec } => spec,
},
@@ -98,7 +98,7 @@ impl RunMatch {
}
pub fn bot_version_to_botspec(
- runner_config: &Arc<GlobalConfig>,
+ runner_config: &GlobalConfig,
bot: Option<&db::bots::Bot>,
bot_version: &db::bots::BotVersion,
) -> Box<dyn BotSpec> {
@@ -120,17 +120,14 @@ pub fn bot_version_to_botspec(
}
}
-fn python_docker_bot_spec(
- runner_config: &Arc<GlobalConfig>,
- code_bundle_path: &str,
-) -> Box<dyn BotSpec> {
- let code_bundle_rel_path = PathBuf::from(BOTS_DIR).join(code_bundle_path);
+fn python_docker_bot_spec(config: &GlobalConfig, code_bundle_path: &str) -> Box<dyn BotSpec> {
+ let code_bundle_rel_path = PathBuf::from(&config.bots_directory).join(code_bundle_path);
let code_bundle_abs_path = std::fs::canonicalize(&code_bundle_rel_path).unwrap();
let code_bundle_path_str = code_bundle_abs_path.as_os_str().to_str().unwrap();
// TODO: it would be good to simplify this configuration
Box::new(DockerBotSpec {
- image: runner_config.python_runner_image.clone(),
+ image: config.python_runner_image.clone(),
binds: Some(vec![format!("{}:{}", code_bundle_path_str, "/workdir")]),
argv: Some(vec!["python".to_string(), "bot.py".to_string()]),
working_dir: Some("/workdir".to_string()),
diff --git a/planetwars-server/src/routes/bots.rs b/planetwars-server/src/routes/bots.rs
index edb68ae..9ddb109 100644
--- a/planetwars-server/src/routes/bots.rs
+++ b/planetwars-server/src/routes/bots.rs
@@ -1,7 +1,7 @@
use axum::extract::{Multipart, Path};
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
-use axum::{body, Json};
+use axum::{body, Extension, Json};
use diesel::OptionalExtension;
use rand::distributions::Alphanumeric;
use rand::Rng;
@@ -9,13 +9,14 @@ use serde::{Deserialize, Serialize};
use serde_json::{self, json, value::Value as JsonValue};
use std::io::Cursor;
use std::path::PathBuf;
+use std::sync::Arc;
use thiserror;
use crate::db::bots::{self, BotVersion};
use crate::db::ratings::{self, RankedBot};
use crate::db::users::User;
use crate::modules::bots::save_code_string;
-use crate::{DatabaseConnection, BOTS_DIR};
+use crate::{DatabaseConnection, GlobalConfig};
use bots::Bot;
#[derive(Serialize, Deserialize, Debug)]
@@ -96,6 +97,7 @@ pub async fn save_bot(
Json(params): Json<SaveBotParams>,
user: User,
conn: DatabaseConnection,
+ Extension(config): Extension<Arc<GlobalConfig>>,
) -> Result<Json<Bot>, SaveBotError> {
let res = bots::find_bot_by_name(&params.bot_name, &conn)
.optional()
@@ -119,8 +121,8 @@ pub async fn save_bot(
bots::create_bot(&new_bot, &conn).expect("could not create bot")
}
};
- let _code_bundle =
- save_code_string(&params.code, Some(bot.id), &conn).expect("failed to save code bundle");
+ let _code_bundle = save_code_string(&params.code, Some(bot.id), &conn, &config)
+ .expect("failed to save code bundle");
Ok(Json(bot))
}
@@ -183,8 +185,9 @@ pub async fn upload_code_multipart(
user: User,
Path(bot_id): Path<i32>,
mut multipart: Multipart,
+ Extension(config): Extension<Arc<GlobalConfig>>,
) -> Result<Json<BotVersion>, StatusCode> {
- let bots_dir = PathBuf::from(BOTS_DIR);
+ let bots_dir = PathBuf::from(&config.bots_directory);
let bot = bots::find_bot(bot_id, &conn).map_err(|_| StatusCode::NOT_FOUND)?;
diff --git a/planetwars-server/src/routes/demo.rs b/planetwars-server/src/routes/demo.rs
index 77f9e8d..69838f3 100644
--- a/planetwars-server/src/routes/demo.rs
+++ b/planetwars-server/src/routes/demo.rs
@@ -46,7 +46,7 @@ pub async fn submit_bot(
let opponent_bot_version = db::bots::active_bot_version(opponent_bot.id, &conn)
.map_err(|_| StatusCode::BAD_REQUEST)?;
- let player_bot_version = save_code_string(&params.code, None, &conn)
+ let player_bot_version = save_code_string(&params.code, None, &conn, &config)
// TODO: can we recover from this?
.expect("could not save bot code");
diff --git a/planetwars-server/src/routes/matches.rs b/planetwars-server/src/routes/matches.rs
index f33a5f1..a980daa 100644
--- a/planetwars-server/src/routes/matches.rs
+++ b/planetwars-server/src/routes/matches.rs
@@ -1,11 +1,11 @@
-use axum::{extract::Path, Json};
+use axum::{extract::Path, Extension, Json};
use hyper::StatusCode;
use serde::{Deserialize, Serialize};
-use std::path::PathBuf;
+use std::{path::PathBuf, sync::Arc};
use crate::{
db::matches::{self, MatchState},
- DatabaseConnection, MATCHES_DIR,
+ DatabaseConnection, GlobalConfig,
};
#[derive(Serialize, Deserialize)]
@@ -59,10 +59,11 @@ pub async fn get_match_data(
pub async fn get_match_log(
Path(match_id): Path<i32>,
conn: DatabaseConnection,
+ Extension(config): Extension<Arc<GlobalConfig>>,
) -> Result<Vec<u8>, StatusCode> {
let match_base =
matches::find_match_base(match_id, &conn).map_err(|_| StatusCode::NOT_FOUND)?;
- let log_path = PathBuf::from(MATCHES_DIR).join(&match_base.log_path);
+ let log_path = PathBuf::from(&config.match_logs_directory).join(&match_base.log_path);
let log_contents = std::fs::read(log_path).map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
Ok(log_contents)
}