113 lines
3.2 KiB
Rust
113 lines
3.2 KiB
Rust
use std::{any::Any, clone, env, fmt::Display, sync::LazyLock};
|
|
|
|
use actix_web::{
|
|
App, HttpResponse, HttpResponseBuilder, HttpServer, Responder, ResponseError, Result, get,
|
|
http::{self, StatusCode},
|
|
web,
|
|
};
|
|
use kube::{Api, Resource, api::ListParams, core::object::HasSpec};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use crate::crds::GameServer;
|
|
|
|
static SELF_ENDPOINT: LazyLock<String> =
|
|
LazyLock::new(|| env::var("SELF_ENDPOINT").expect("SELF_ENDPOINT is not specified"));
|
|
|
|
#[derive(Clone, Debug, Serialize)]
|
|
struct ResourceNameDescriptor {
|
|
name: String,
|
|
resource: String,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
struct KubeError(kube::Error);
|
|
|
|
impl Display for KubeError {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
self.0.fmt(f)
|
|
}
|
|
}
|
|
|
|
impl ResponseError for KubeError {
|
|
fn status_code(&self) -> http::StatusCode {
|
|
StatusCode::INTERNAL_SERVER_ERROR
|
|
}
|
|
|
|
fn error_response(&self) -> HttpResponse<actix_web::body::BoxBody> {
|
|
HttpResponseBuilder::new(self.status_code()).body(self.0.to_string())
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct HashParam {
|
|
hash: Option<u64>,
|
|
}
|
|
|
|
#[get("/gameserver/discover")]
|
|
async fn gameservers(kube_client: web::Data<kube::Client>) -> Result<impl Responder> {
|
|
let servers: Api<GameServer> = Api::all(kube_client.get_ref().clone());
|
|
|
|
let servers = servers
|
|
.list_metadata(&ListParams::default())
|
|
.await
|
|
.map_err(KubeError)?;
|
|
|
|
let list: Vec<_> = servers
|
|
.into_iter()
|
|
.map(|v| ResourceNameDescriptor {
|
|
name: v.metadata.name.clone().unwrap(),
|
|
resource: format!(
|
|
"{}/gameserver/{}",
|
|
&*SELF_ENDPOINT,
|
|
v.metadata.name.unwrap()
|
|
),
|
|
})
|
|
.collect();
|
|
|
|
Ok(web::Json(list))
|
|
}
|
|
|
|
#[get("/gameserver/{game_name}")]
|
|
async fn get_gameserver(
|
|
kube_client: web::Data<kube::Client>,
|
|
path: web::Path<(String)>,
|
|
) -> Result<impl Responder> {
|
|
let (game_name) = path.into_inner();
|
|
let servers: Api<GameServer> = Api::all(kube_client.get_ref().clone());
|
|
|
|
let game_server = servers.get(&game_name).await.map_err(KubeError)?;
|
|
let game_server_spec = game_server.spec();
|
|
|
|
Ok(web::Json(game_server_spec.clone()))
|
|
}
|
|
|
|
#[get("/gameserver/{game_name}/auth_proxy")]
|
|
async fn get_gameserver_proxy(
|
|
kube_client: web::Data<kube::Client>,
|
|
path: web::Path<String>,
|
|
param: web::Query<HashParam>,
|
|
) -> Result<impl Responder> {
|
|
let game_name = path.into_inner();
|
|
let hash = param.0.hash.unwrap_or(0);
|
|
let servers: Api<GameServer> = Api::all(kube_client.get_ref().clone());
|
|
|
|
let game_server = servers.get(&game_name).await.map_err(KubeError)?;
|
|
let game_server_spec = game_server.spec();
|
|
|
|
Ok(web::Json(game_server_spec.clone()))
|
|
}
|
|
|
|
pub async fn start_webserver(kube_client: kube::Client) {
|
|
HttpServer::new(move || {
|
|
App::new()
|
|
.app_data(web::Data::new(kube_client.clone()))
|
|
.service(gameservers)
|
|
.service(get_gameserver)
|
|
.service(get_gameserver_proxy)
|
|
})
|
|
.bind(("127.0.0.1", 8080))
|
|
.expect("failed to start webserver")
|
|
.run()
|
|
.await
|
|
.expect("error occurred whilest running webserver");
|
|
}
|