embed migrations, fix start, add stop
This commit is contained in:
85
Cargo.lock
generated
85
Cargo.lock
generated
@ -561,6 +561,17 @@ dependencies = [
|
|||||||
"syn 2.0.117",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "diesel_migrations"
|
||||||
|
version = "2.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "28d0f4a98124ba6d4ca75da535f65984badec16a003b6e2f94a01e31a79490b8"
|
||||||
|
dependencies = [
|
||||||
|
"diesel",
|
||||||
|
"migrations_internals",
|
||||||
|
"migrations_macros",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "diesel_table_macro_syntax"
|
name = "diesel_table_macro_syntax"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@ -604,6 +615,7 @@ dependencies = [
|
|||||||
"clap",
|
"clap",
|
||||||
"diesel",
|
"diesel",
|
||||||
"diesel-enum",
|
"diesel-enum",
|
||||||
|
"diesel_migrations",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"json",
|
"json",
|
||||||
"num-derive",
|
"num-derive",
|
||||||
@ -1300,6 +1312,27 @@ version = "2.8.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "migrations_internals"
|
||||||
|
version = "2.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "36c791ecdf977c99f45f23280405d7723727470f6689a5e6dbf513ac547ae10d"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"toml",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "migrations_macros"
|
||||||
|
version = "2.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "36fc5ac76be324cfd2d3f2cf0fdf5d5d3c4f14ed8aaebadb09e304ba42282703"
|
||||||
|
dependencies = [
|
||||||
|
"migrations_internals",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.8.9"
|
version = "0.8.9"
|
||||||
@ -1667,6 +1700,15 @@ dependencies = [
|
|||||||
"syn 2.0.117",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_spanned"
|
||||||
|
version = "1.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_urlencoded"
|
name = "serde_urlencoded"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
@ -1904,6 +1946,37 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.9.12+spec-1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_parser",
|
||||||
|
"winnow 0.7.15",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_datetime"
|
||||||
|
version = "0.7.5+spec-1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_parser"
|
||||||
|
version = "1.1.2+spec-1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
|
||||||
|
dependencies = [
|
||||||
|
"winnow 1.0.3",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower-service"
|
name = "tower-service"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
@ -2207,6 +2280,18 @@ dependencies = [
|
|||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.7.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wit-bindgen"
|
name = "wit-bindgen"
|
||||||
version = "0.51.0"
|
version = "0.51.0"
|
||||||
|
|||||||
@ -10,6 +10,7 @@ chrono = "0.4.44"
|
|||||||
clap = "4.6.1"
|
clap = "4.6.1"
|
||||||
diesel = { version = "2.3.9", features = ["sqlite", "r2d2", "chrono"] }
|
diesel = { version = "2.3.9", features = ["sqlite", "r2d2", "chrono"] }
|
||||||
diesel-enum = "0.2.1"
|
diesel-enum = "0.2.1"
|
||||||
|
diesel_migrations = "2.3.2"
|
||||||
futures-util = "0.3.32"
|
futures-util = "0.3.32"
|
||||||
json = "0.12.4"
|
json = "0.12.4"
|
||||||
num-derive = "0.4.2"
|
num-derive = "0.4.2"
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
CREATE TABLE "servers" (
|
CREATE TABLE "servers" (
|
||||||
"name" varchar(255) UNIQUE NOT NULL PRIMARY KEY,
|
"name" varchar(255) UNIQUE NOT NULL PRIMARY KEY,
|
||||||
"last_login" timestamp,
|
"last_login" timestamp,
|
||||||
"container_id" varchar(30),
|
|
||||||
"status" INT2 NOT NULL DEFAULT 0,
|
"status" INT2 NOT NULL DEFAULT 0,
|
||||||
"is_default" bool NOT NULL DEFAULT false,
|
"is_default" bool NOT NULL DEFAULT false,
|
||||||
"redirect_ip" varchar(50)
|
"redirect_ip" varchar(50)
|
||||||
);
|
);
|
||||||
|
|
||||||
insert into servers (name, last_login, container_id, status, is_default, redirect_ip) values ('potato', datetime(), null, 1, false, 'play.hypixel.net:25565');
|
insert into servers (name, last_login, status, is_default, redirect_ip) values ('potato', datetime(), 4, false, 'play.hypixel.net:25565');
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
use chrono::Utc;
|
||||||
use clap::{ArgMatches, Command, arg};
|
use clap::{ArgMatches, Command, arg};
|
||||||
use crate::cli::env_settings;
|
use crate::cli::env_settings;
|
||||||
use crate::status::ServerStatus;
|
use crate::status::ServerStatus;
|
||||||
@ -9,7 +10,7 @@ use crate::{DbPool, models}; use crate::schema;
|
|||||||
use tokio::{fs::{File, create_dir}, io::AsyncWriteExt};
|
use tokio::{fs::{File, create_dir}, io::AsyncWriteExt};
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::time::SystemTime;
|
|
||||||
|
|
||||||
pub fn create_subcommand() -> Command {
|
pub fn create_subcommand() -> Command {
|
||||||
let mut arguments = vec![
|
let mut arguments = vec![
|
||||||
@ -56,15 +57,13 @@ pub async fn subcommand(arg: &ArgMatches, pool: DbPool) -> Result<(), String>{
|
|||||||
std::fs::remove_dir_all(path.to_string() + "tmp").map_err(|e| format!("failed to remove the tmp dir, reason : {}", e))?;
|
std::fs::remove_dir_all(path.to_string() + "tmp").map_err(|e| format!("failed to remove the tmp dir, reason : {}", e))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let _new_server = models::CreateServer {
|
let new_server = models::CreateServer {
|
||||||
name: server_name,
|
name: server_name,
|
||||||
last_login: Some(SystemTime::now()),
|
last_login: Some(Utc::now().naive_utc()),
|
||||||
container_id: None,
|
|
||||||
status: ServerStatus::Stopped,
|
status: ServerStatus::Stopped,
|
||||||
redirect_ip: None
|
redirect_ip: None
|
||||||
};
|
};
|
||||||
|
|
||||||
// diesel::insert_into(schema::servers::dsl::servers).values(&new_server).execute(conn).map_err(|e| format!("Failed to insert in db, error : {:?}", e))?;
|
diesel::insert_into(servers).values(&new_server).execute(conn).map_err(|e| format!("Failed to insert in db, error : {:?}", e))?;
|
||||||
// TODO: fix weird error
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ pub mod edit;
|
|||||||
pub mod remove;
|
pub mod remove;
|
||||||
pub mod ls;
|
pub mod ls;
|
||||||
pub mod start;
|
pub mod start;
|
||||||
|
pub mod stop;
|
||||||
|
|
||||||
pub mod env_settings;
|
pub mod env_settings;
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,14 @@
|
|||||||
use bollard::Docker;
|
use bollard::Docker;
|
||||||
|
use chrono::Utc;
|
||||||
use clap::Arg;
|
use clap::Arg;
|
||||||
use clap::{Command, ArgMatches};
|
use clap::{Command, ArgMatches};
|
||||||
|
|
||||||
use crate::DbPool;
|
use crate::{ DbPool, schema };
|
||||||
|
|
||||||
use crate::dockermgr;
|
use crate::dockermgr;
|
||||||
|
|
||||||
|
use diesel::prelude::*;
|
||||||
|
|
||||||
pub fn create_subcommand() -> Command {
|
pub fn create_subcommand() -> Command {
|
||||||
Command::new("start")
|
Command::new("start")
|
||||||
.about("manually start a server (and set last login datetime to now)")
|
.about("manually start a server (and set last login datetime to now)")
|
||||||
@ -13,8 +16,11 @@ pub fn create_subcommand() -> Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn subcommand(arguments: &ArgMatches, pool: &DbPool, docker: Docker) -> Result<(), String> {
|
pub async fn subcommand(arguments: &ArgMatches, pool: &DbPool, docker: Docker) -> Result<(), String> {
|
||||||
|
use schema::servers::dsl::*;
|
||||||
let server_name = arguments.get_one::<String>("NAME").unwrap();
|
let server_name = arguments.get_one::<String>("NAME").unwrap();
|
||||||
dockermgr::start_server(&docker, pool, server_name).await?;
|
dockermgr::start_server(&docker, pool, server_name).await?;
|
||||||
|
|
||||||
|
diesel::update(servers).filter(name.eq(server_name)).set(last_login.eq(Utc::now().naive_utc())).execute(&mut pool.get().unwrap()).map_err(|e| format!("Failed to set the last login date: {}", e))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
22
src/cli/stop.rs
Normal file
22
src/cli/stop.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use bollard::Docker;
|
||||||
|
use clap::Arg;
|
||||||
|
use clap::{Command, ArgMatches};
|
||||||
|
|
||||||
|
use crate::DbPool;
|
||||||
|
|
||||||
|
use crate::dockermgr;
|
||||||
|
|
||||||
|
pub fn create_subcommand() -> Command {
|
||||||
|
Command::new("stop")
|
||||||
|
.about("manually stop a server")
|
||||||
|
.arg(Arg::new("NAME").required(true))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn subcommand(arguments: &ArgMatches, pool: &DbPool, docker: Docker) -> Result<(), String> {
|
||||||
|
let server_name = arguments.get_one::<String>("NAME").unwrap();
|
||||||
|
println!("Stopping container");
|
||||||
|
dockermgr::stop_server(&docker, pool, server_name).await?;
|
||||||
|
println!("container stopped");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@ -2,3 +2,6 @@ mod start;
|
|||||||
pub use start::start_server;
|
pub use start::start_server;
|
||||||
|
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
|
mod stop;
|
||||||
|
pub use stop::stop_server;
|
||||||
|
|||||||
@ -48,13 +48,14 @@ async fn start_docker_container(docker: &Docker, name: &String) -> Result<String
|
|||||||
|
|
||||||
println!("starting container");
|
println!("starting container");
|
||||||
docker.start_container(&container_name, None).await.map_err(|e| format!("Failed to start the container : {}", e))?;
|
docker.start_container(&container_name, None).await.map_err(|e| format!("Failed to start the container : {}", e))?;
|
||||||
Ok(get_container_ip(docker, name).await?)
|
Ok(get_container_ip(docker, &container_name).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub async fn start_server(docker: &Docker, pool: &DbPool, server_name: &String) -> Result<(), String> {
|
pub async fn start_server(docker: &Docker, pool: &DbPool, server_name: &String) -> Result<(), String> {
|
||||||
use schema::servers::dsl::*;
|
use schema::servers::dsl::*;
|
||||||
|
|
||||||
let conn = &mut pool.get().unwrap();
|
let conn = &mut pool.get().unwrap();
|
||||||
|
|
||||||
let server = match servers.select(models::Servers::as_select()).filter(name.eq(server_name)).first(conn) {
|
let server = match servers.select(models::Servers::as_select()).filter(name.eq(server_name)).first(conn) {
|
||||||
Err(NotFound) => { return Err("This server does not exist".to_string()); },
|
Err(NotFound) => { return Err("This server does not exist".to_string()); },
|
||||||
@ -66,10 +67,14 @@ pub async fn start_server(docker: &Docker, pool: &DbPool, server_name: &String)
|
|||||||
return Err("Server is starting, please wait".to_string());
|
return Err("Server is starting, please wait".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if server.status != ServerStatus::Stopped {
|
||||||
|
return Err(format!("Invalid server state({}), refusing to start", server.status));
|
||||||
|
}
|
||||||
|
|
||||||
diesel::update(servers).filter(name.eq(server_name)).set(status.eq(ServerStatus::Starting)).execute(conn).map_err(|e| format!("Failed to set server to starting : {}", e))?;
|
diesel::update(servers).filter(name.eq(server_name)).set(status.eq(ServerStatus::Starting)).execute(conn).map_err(|e| format!("Failed to set server to starting : {}", e))?;
|
||||||
|
|
||||||
let ip = start_docker_container(docker, server_name).await?;
|
let ip = start_docker_container(docker, server_name).await?;
|
||||||
|
|
||||||
diesel::update(servers).filter(name.eq(server_name)).set((status.eq(ServerStatus::Starting), redirect_ip.eq(ip.to_string()))).execute(conn).map_err(|e| format!("Failed to set server to starting : {}", e))?;
|
diesel::update(servers).filter(name.eq(server_name)).set((status.eq(ServerStatus::Running), redirect_ip.eq(ip.to_string() + ":25565"))).execute(conn).map_err(|e| format!("Failed to set server to starting : {}", e))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
41
src/dockermgr/stop.rs
Normal file
41
src/dockermgr/stop.rs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
use bollard::{Docker, query_parameters::StopContainerOptionsBuilder};
|
||||||
|
use diesel::result::Error::NotFound;
|
||||||
|
|
||||||
|
use diesel::prelude::*;
|
||||||
|
|
||||||
|
use crate::{ DbPool, models, schema, status::ServerStatus };
|
||||||
|
|
||||||
|
|
||||||
|
async fn stop_container(docker: &Docker, name: &String) -> Result<(), String> {
|
||||||
|
let container_name = format!("minecraft-{}", name);
|
||||||
|
|
||||||
|
let options = StopContainerOptionsBuilder::new()
|
||||||
|
.t(60)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
docker.stop_container(&container_name, Some(options)).await.map_err(|e| format!("Failed to stop the container : {}", e))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn stop_server(docker: &Docker, pool: &DbPool, server_name: &String) -> Result<(), String> {
|
||||||
|
use schema::servers::dsl::*;
|
||||||
|
|
||||||
|
let conn = &mut pool.get().unwrap();
|
||||||
|
|
||||||
|
let server = match servers.select(models::Servers::as_select()).filter(name.eq(server_name)).first(conn) {
|
||||||
|
Err(NotFound) => { return Err("This server does not exist".to_string()); },
|
||||||
|
Err(e) => { return Err(format!("Failed to get server from db : {}", e)) },
|
||||||
|
Ok(server) => { server }
|
||||||
|
};
|
||||||
|
|
||||||
|
if server.status != ServerStatus::Running {
|
||||||
|
return Err(format!("Invalid server state ({}), refusing to stop the server", server.status));
|
||||||
|
}
|
||||||
|
|
||||||
|
diesel::update(servers).filter(name.eq(server_name)).set(status.eq(ServerStatus::Stopping)).execute(conn).map_err(|e| format!("Failed to set the server state to stopping : {}", e))?;
|
||||||
|
|
||||||
|
stop_container(docker, server_name).await?;
|
||||||
|
|
||||||
|
diesel::update(servers).filter(name.eq(server_name)).set((redirect_ip.eq(None::<String>), status.eq(ServerStatus::Stopped))).execute(conn).map_err(|e| format!("Failed to set the server state to stopped : {}", e))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@ -1,9 +1,12 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use bollard::{Docker, plugin::{ContainerInspectResponse, ContainerSummary, ImageId}, query_parameters::{CreateImageOptionsBuilder, ListContainersOptionsBuilder, ListImagesOptionsBuilder}};
|
use bollard::{
|
||||||
|
Docker,
|
||||||
|
plugin::{ContainerInspectResponse},
|
||||||
|
query_parameters::{CreateImageOptionsBuilder, ListImagesOptionsBuilder}
|
||||||
|
};
|
||||||
|
|
||||||
use futures_util::stream::StreamExt;
|
use futures_util::stream::StreamExt;
|
||||||
use tokio::task;
|
|
||||||
|
|
||||||
pub async fn check_image(docker: &Docker) -> Result<(), String> {
|
pub async fn check_image(docker: &Docker) -> Result<(), String> {
|
||||||
let mut filters = HashMap::new();
|
let mut filters = HashMap::new();
|
||||||
@ -54,8 +57,9 @@ pub async fn get_container_ip(docker: &Docker, name: &String) -> Result<String,
|
|||||||
let mut retries = 20;
|
let mut retries = 20;
|
||||||
|
|
||||||
while retries > 0 {
|
while retries > 0 {
|
||||||
let container = get_container(docker, name).await.unwrap();
|
let container = get_container(docker, name).await;
|
||||||
if let Some(network) = container.network_settings.unwrap().networks.unwrap().get("bridge") {
|
|
||||||
|
if let Some(container) = container && let Some(network) = container.network_settings.unwrap().networks.unwrap().get("bridge") {
|
||||||
if let Some(ip) = &network.ip_address {
|
if let Some(ip) = &network.ip_address {
|
||||||
return Ok(ip.to_string());
|
return Ok(ip.to_string());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
/* By: tomoron <tomoron@student.42angouleme.fr> +#+ +:+ +#+ */
|
/* By: tomoron <tomoron@student.42angouleme.fr> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2026/05/29 21:22:17 by tomoron #+# #+# */
|
/* Created: 2026/05/29 21:22:17 by tomoron #+# #+# */
|
||||||
/* Updated: 2026/06/09 00:05:23 by tomoron ### ########.fr */
|
/* Updated: 2026/06/09 17:04:32 by tomoron ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
@ -34,6 +34,8 @@ pub type DbPool = Pool<ConnectionManager<SqliteConnection>>;
|
|||||||
|
|
||||||
use bollard::Docker;
|
use bollard::Docker;
|
||||||
|
|
||||||
|
mod migrations;
|
||||||
|
|
||||||
fn get_connection_pool() -> DbPool {
|
fn get_connection_pool() -> DbPool {
|
||||||
let database_url = "sqlite://".to_string() + &Config::load().config_path + "/db.sqlite";
|
let database_url = "sqlite://".to_string() + &Config::load().config_path + "/db.sqlite";
|
||||||
|
|
||||||
@ -59,12 +61,16 @@ fn cli() -> Command {
|
|||||||
.subcommand(edit::create_subcommand())
|
.subcommand(edit::create_subcommand())
|
||||||
.subcommand(ls::create_subcommand())
|
.subcommand(ls::create_subcommand())
|
||||||
.subcommand(start::create_subcommand())
|
.subcommand(start::create_subcommand())
|
||||||
|
.subcommand(stop::create_subcommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main(flavor = "current_thread")]
|
#[tokio::main(flavor = "current_thread")]
|
||||||
async fn main() -> Result<(), String> {
|
async fn main() -> Result<(), String> {
|
||||||
let arg = cli().get_matches();
|
let arg = cli().get_matches();
|
||||||
let pool = get_connection_pool();
|
let pool = get_connection_pool();
|
||||||
|
|
||||||
|
migrations::run_migrations(&pool).map_err(|e| format!("Failed to run migrations : {}", e))?;
|
||||||
|
|
||||||
let docker = Docker::connect_with_defaults().expect("Failed to connect to local docker");
|
let docker = Docker::connect_with_defaults().expect("Failed to connect to local docker");
|
||||||
|
|
||||||
match arg.subcommand() {
|
match arg.subcommand() {
|
||||||
@ -75,6 +81,7 @@ async fn main() -> Result<(), String> {
|
|||||||
Some(("edit", sub_matches)) => { edit::subcommand(sub_matches, pool).await?; },
|
Some(("edit", sub_matches)) => { edit::subcommand(sub_matches, pool).await?; },
|
||||||
|
|
||||||
Some(("start", sub_matches)) => { start::subcommand(sub_matches, &pool, docker).await?; },
|
Some(("start", sub_matches)) => { start::subcommand(sub_matches, &pool, docker).await?; },
|
||||||
|
Some(("stop", sub_matches)) => { stop::subcommand(sub_matches, &pool, docker).await?; },
|
||||||
_ => {panic!("subcommand not implemented")}
|
_ => {panic!("subcommand not implemented")}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
19
src/migrations.rs
Normal file
19
src/migrations.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
|
||||||
|
|
||||||
|
use crate::DbPool;
|
||||||
|
pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("./migrations");
|
||||||
|
|
||||||
|
|
||||||
|
pub fn run_migrations(pool: &DbPool) -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
|
||||||
|
|
||||||
|
// This will run the necessary migrations.
|
||||||
|
//
|
||||||
|
// See the documentation for `MigrationHarness` for
|
||||||
|
// all available methods.
|
||||||
|
let connection = &mut pool.get().unwrap();
|
||||||
|
connection.run_pending_migrations(MIGRATIONS)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@ -1,11 +1,8 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::time::SystemTime;
|
|
||||||
|
|
||||||
use chrono::{DateTime, NaiveDateTime, TimeZone, Utc};
|
use chrono::{DateTime, NaiveDateTime, TimeZone, Utc};
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
|
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
use crate::status::ServerStatus;
|
use crate::status::ServerStatus;
|
||||||
|
|
||||||
use crate::schema;
|
use crate::schema;
|
||||||
@ -16,18 +13,16 @@ use crate::schema;
|
|||||||
pub struct Servers {
|
pub struct Servers {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub last_login: Option<NaiveDateTime>,
|
pub last_login: Option<NaiveDateTime>,
|
||||||
pub container_id: Option<String>,
|
|
||||||
pub status: ServerStatus,
|
pub status: ServerStatus,
|
||||||
pub redirect_ip: Option<String>
|
pub redirect_ip: Option<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Deserialize, Insertable)]
|
#[derive(Insertable)]
|
||||||
#[diesel(table_name = schema::servers)]
|
#[diesel(table_name = schema::servers)]
|
||||||
pub struct CreateServer<'a> {
|
pub struct CreateServer<'a> {
|
||||||
pub name: &'a str,
|
pub name: &'a str,
|
||||||
pub last_login: Option<SystemTime>,
|
pub last_login: Option<NaiveDateTime>,
|
||||||
pub container_id: Option<&'a str>,
|
|
||||||
pub status: ServerStatus,
|
pub status: ServerStatus,
|
||||||
pub redirect_ip: Option<&'a str>
|
pub redirect_ip: Option<&'a str>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,6 @@ diesel::table! {
|
|||||||
servers (name) {
|
servers (name) {
|
||||||
name -> Text,
|
name -> Text,
|
||||||
last_login -> Nullable<Timestamp>,
|
last_login -> Nullable<Timestamp>,
|
||||||
container_id -> Nullable<Text>,
|
|
||||||
status -> SmallInt,
|
status -> SmallInt,
|
||||||
is_default -> Bool,
|
is_default -> Bool,
|
||||||
redirect_ip -> Nullable<Text>,
|
redirect_ip -> Nullable<Text>,
|
||||||
|
|||||||
@ -32,7 +32,7 @@ impl FromSql<SmallInt, Sqlite> for ServerStatus{
|
|||||||
impl ToSql<SmallInt, Sqlite> for ServerStatus {
|
impl ToSql<SmallInt, Sqlite> for ServerStatus {
|
||||||
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> diesel::serialize::Result {
|
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> diesel::serialize::Result {
|
||||||
let value: i16 = self.clone() as i16;
|
let value: i16 = self.clone() as i16;
|
||||||
out.set_value(value.to_le_bytes().to_vec());
|
out.set_value(value as i32);
|
||||||
Ok(diesel::serialize::IsNull::No)
|
Ok(diesel::serialize::IsNull::No)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user