start to implement the configuration file and mrproxy integration

This commit is contained in:
2025-12-20 03:56:46 +00:00
parent 7cabefc76e
commit 5045c05f9f
11 changed files with 323 additions and 15 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
/target/ /target/
/mdeploy.db /mdeploy.db
/mrdeploy_data/ /mrdeploy_data/
/config/config.toml

55
Cargo.lock generated
View File

@@ -1266,6 +1266,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"tokio", "tokio",
"toml",
] ]
[[package]] [[package]]
@@ -1623,6 +1624,15 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "serde_spanned"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776"
dependencies = [
"serde_core",
]
[[package]] [[package]]
name = "serde_urlencoded" name = "serde_urlencoded"
version = "0.7.1" version = "0.7.1"
@@ -1847,6 +1857,45 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "toml"
version = "0.9.10+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0825052159284a1a8b4d6c0c86cbc801f2da5afd2b225fa548c72f2e74002f48"
dependencies = [
"indexmap 2.12.1",
"serde_core",
"serde_spanned",
"toml_datetime",
"toml_parser",
"toml_writer",
"winnow",
]
[[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.0.6+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44"
dependencies = [
"winnow",
]
[[package]]
name = "toml_writer"
version = "1.0.6+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607"
[[package]] [[package]]
name = "tower-service" name = "tower-service"
version = "0.3.3" version = "0.3.3"
@@ -2257,6 +2306,12 @@ version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
[[package]]
name = "winnow"
version = "0.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829"
[[package]] [[package]]
name = "wit-bindgen" name = "wit-bindgen"
version = "0.46.0" version = "0.46.0"

View File

@@ -15,6 +15,7 @@ log = "0.4"
serde = "*" serde = "*"
serde_json = "*" serde_json = "*"
fallible-iterator = "*" fallible-iterator = "*"
toml = "0.9"
[target.x86_64-unknown-linux-gnu] [target.x86_64-unknown-linux-gnu]
rustflags = [ rustflags = [

View File

@@ -0,0 +1,7 @@
[docker]
connection = "http"
string = "http://my-custom-docker-server:2735"
[mrproxy]
connection = "tcp"
string = "127.0.0.1:25564"

102
src/config/mod.rs Normal file
View File

@@ -0,0 +1,102 @@
use std::{error::Error, fs::read_to_string, io};
use toml::Table;
pub const CONFIG_PATH: &str = "config/config.tom";
enum DockerConnectionKind {
HTTP,
HTTP_DEFAULT,
UNIX,
UNIX_DEFAULT,
}
pub enum MrproxyConnectionKind {
TCP,
UNIX,
}
pub struct DockerConnectionConfig {
connection_kind: DockerConnectionKind,
connection_string: Option<String>,
}
pub struct MrproxyConnectionData {
pub connection_kind: MrproxyConnectionKind,
pub connection_string: String,
}
impl DockerConnectionConfig {
pub fn get_config(file_name: &str) -> Result<Self, Box<dyn Error>> {
let stored_file = read_to_string(file_name)?.parse::<Table>()?;
let connection_kind_string = stored_file["docker"]["connection"].as_str().ok_or(
generate_toml_parser_error_in_field("docker connection kind"),
)?;
let connection_kind = match connection_kind_string {
"http" => DockerConnectionKind::HTTP,
"http_default" => DockerConnectionKind::HTTP_DEFAULT,
"unix" => DockerConnectionKind::UNIX,
"unix_default" => DockerConnectionKind::UNIX_DEFAULT,
_ => {
return Err(Box::new(generate_toml_parser_error_in_field(
"docker connection kind",
)));
}
};
let connection_string = match connection_kind {
DockerConnectionKind::HTTP | DockerConnectionKind::UNIX => Some(
stored_file["docker"]["string"]
.as_str()
.ok_or(generate_toml_parser_error_in_field(
"docker connection string",
))?
.to_string(),
),
_ => None,
};
Ok(Self {
connection_kind,
connection_string,
})
}
}
impl MrproxyConnectionData {
pub fn get_config(file_name: &str) -> Result<Self, Box<dyn Error>> {
let stored_file = read_to_string(file_name)?.parse::<Table>()?;
let connection_kind_string = stored_file["mrproxy"]["connection"].as_str().ok_or(
generate_toml_parser_error_in_field("mrproxy connection kind"),
)?;
let connection_kind = match connection_kind_string {
"tcp" => MrproxyConnectionKind::TCP,
"unix" => MrproxyConnectionKind::UNIX,
_ => {
return Err(Box::new(generate_toml_parser_error_in_field(
"mrproxy connection kind",
)));
}
};
let connection_string = stored_file["mrproxy"]["string"]
.as_str()
.ok_or(generate_toml_parser_error_in_field(
"mrproxy connection string",
))?
.to_string();
Ok(Self {
connection_kind,
connection_string,
})
}
}
fn generate_toml_parser_error_in_field(field: &str) -> io::Error {
io::Error::new(
io::ErrorKind::InvalidData,
format!("Invalid format for config.toml in {} field", field),
)
}

View File

@@ -1,11 +1,14 @@
use crate::config::{DockerConnectionConfig, MrproxyConnectionData};
use crate::database::exposer::MemStorage; use crate::database::exposer::MemStorage;
use crate::database::instance::Instance; use crate::database::instance::Instance;
use crate::deploy;
use crate::deploy::container::Container; use crate::deploy::container::Container;
use crate::deploy::container_options::Options; use crate::deploy::container_options::Options;
use crate::mcproxy_client::client;
use crate::{deploy, mcproxy_client};
use bollard::errors::Error; use bollard::errors::Error;
use bollard::Docker; use bollard::Docker;
use log::error; use log::error;
use std::os::unix::net::UnixStream;
use std::sync::Mutex; use std::sync::Mutex;
pub struct Controller { pub struct Controller {
@@ -13,6 +16,8 @@ pub struct Controller {
network: String, network: String,
storage: Mutex<MemStorage>, storage: Mutex<MemStorage>,
started: bool, started: bool,
docker_config: DockerConnectionConfig,
mrproxy_config: MrproxyConnectionData,
} }
impl Controller { impl Controller {
@@ -20,6 +25,8 @@ impl Controller {
driver: Docker, driver: Docker,
network: String, network: String,
range: String, range: String,
docker_config: DockerConnectionConfig,
mrproxy_config: MrproxyConnectionData,
) -> Result<Self, bollard::errors::Error> { ) -> Result<Self, bollard::errors::Error> {
deploy::network::Network::new(driver.clone(), network.clone(), range).await?; deploy::network::Network::new(driver.clone(), network.clone(), range).await?;
let cont = Self { let cont = Self {
@@ -27,6 +34,8 @@ impl Controller {
network: network, network: network,
storage: Mutex::new(MemStorage::new().unwrap()), storage: Mutex::new(MemStorage::new().unwrap()),
started: false, started: false,
docker_config,
mrproxy_config,
}; };
Ok(cont) Ok(cont)
} }
@@ -40,16 +49,31 @@ impl Controller {
) -> String { ) -> String {
let is_stored = self.storage.lock().unwrap().search_instance(domain.clone()); let is_stored = self.storage.lock().unwrap().search_instance(domain.clone());
match is_stored { match is_stored {
Some(c) => match c.docker_id { Some(c) => {
let mut mrcp_controller =
mcproxy_client::controller::Controller::new(&self.mrproxy_config).unwrap();
_ = mrcp_controller.insert_new_domain(
&domain,
&ip.unwrap_or(c.get_ip(&self.driver).await.unwrap()),
);
match c.docker_id {
Some(id) => id, Some(id) => id,
None => "Container without docker_id".to_string(), None => "Container without docker_id".to_string(),
}, }
}
None => { None => {
match self match self
.load_container(None, domain.clone(), ip.clone(), image.clone(), ops) .load_container(None, domain.clone(), ip.clone(), image.clone(), ops)
.await .await
{ {
Ok(c) => { Ok(c) => {
let mut mrcp_controller =
mcproxy_client::controller::Controller::new(&self.mrproxy_config)
.unwrap();
_ = mrcp_controller.insert_new_domain(
&domain,
&ip.unwrap_or(c.get_ip(&self.driver).await.unwrap()),
);
self.storage self.storage
.try_lock() .try_lock()
.unwrap() .unwrap()

View File

@@ -1,17 +1,23 @@
use crate::{config, controller::Controller};
use bollard::Docker; use bollard::Docker;
use crate::controller::Controller;
pub async fn start_docker() -> Controller{ pub async fn start_docker() -> Controller {
let docker = match Docker::connect_with_local_defaults() { let docker = match Docker::connect_with_local_defaults() {
Ok(d) => d, Ok(d) => d,
Err(e) => panic!("error:{}",e.to_string()), Err(e) => panic!("error:{}", e.to_string()),
}; };
env_logger::init_from_env(env_logger::Env::new().default_filter_or("debug")); env_logger::init_from_env(env_logger::Env::new().default_filter_or("debug"));
let controller = match Controller::new(docker, let controller = match Controller::new(
docker,
"customnetwork".to_string(), "customnetwork".to_string(),
"172.20.0.0/24".to_string()).await { "172.20.0.0/24".to_string(),
config::DockerConnectionConfig::get_config(config::CONFIG_PATH).unwrap(),
config::MrproxyConnectionData::get_config(config::CONFIG_PATH).unwrap(),
)
.await
{
Ok(c) => c, Ok(c) => c,
Err(e) => panic!("error: {}",e), Err(e) => panic!("error: {}", e),
}; };
controller.load_all_instances().await; controller.load_all_instances().await;
return controller; return controller;

View File

@@ -1,7 +1,9 @@
mod api; mod api;
mod config;
mod controller; mod controller;
mod database; mod database;
mod deploy; mod deploy;
mod mcproxy_client;
#[actix_web::main] #[actix_web::main]
async fn main() { async fn main() {

View File

@@ -0,0 +1,30 @@
use std::io::{Read, Result, Write};
pub fn insert_new_domain(stream: &mut dyn Write, domain: &str, ip: &str) -> Result<()> {
_ = stream.write(&[0 as u8]);
let domain = domain.as_bytes();
let ip = ip.as_bytes();
_ = stream.write(&[domain.len() as u8]);
_ = stream.write(domain);
_ = stream.write(&[ip.len() as u8]);
_ = stream.write(ip);
Ok(())
}
pub fn remove_domain(stream: &mut dyn Write, domain: &str) -> Result<()> {
_ = stream.write(&[1 as u8])?;
_ = stream.write(&[domain.len() as u8])?;
_ = stream.write(domain.as_bytes())?;
Ok(())
}
pub fn read_response(stream: &mut dyn Read) -> Result<u8> {
let mut buf: [u8; 1] = [1; 1];
_ = stream.read_exact(&mut buf)?;
Ok(buf[0])
}
pub fn close_connection(stream: &mut dyn Write) -> Result<()> {
_ = stream.write(&[2 as u8])?;
Ok(())
}

View File

@@ -0,0 +1,78 @@
use std::{error::Error, net::TcpStream, os::unix::net::UnixStream};
use crate::{
config::{
MrproxyConnectionData,
MrproxyConnectionKind::{TCP, UNIX},
},
mcproxy_client::client,
};
enum KindStream {
TCP,
UNIX,
}
pub struct Controller {
tcp_stream: Option<TcpStream>,
unix_stream: Option<UnixStream>,
kind_stream: KindStream,
}
impl Controller {
pub fn new(conexion_data: &MrproxyConnectionData) -> Result<Self, Box<dyn Error>> {
let streams: (Option<TcpStream>, Option<UnixStream>, KindStream) =
match conexion_data.connection_kind {
TCP => (
Some(TcpStream::connect(&conexion_data.connection_string).unwrap()),
None,
KindStream::TCP,
),
UNIX => (
None,
Some(UnixStream::connect(&conexion_data.connection_string).unwrap()),
KindStream::UNIX,
),
};
Ok(Self {
tcp_stream: streams.0,
unix_stream: streams.1,
kind_stream: streams.2,
})
}
pub fn insert_new_domain(&mut self, domain: &str, ip: &str) -> Result<u8, std::io::Error> {
match self.kind_stream {
KindStream::TCP => {
_ = client::insert_new_domain(self.tcp_stream.as_mut().unwrap(), domain, ip)?;
client::read_response(self.tcp_stream.as_mut().unwrap())
}
KindStream::UNIX => {
_ = client::insert_new_domain(self.unix_stream.as_mut().unwrap(), domain, ip)?;
client::read_response(self.unix_stream.as_mut().unwrap())
}
}
}
pub fn remove_domain(&mut self, domain: &str) -> Result<u8, std::io::Error> {
match self.kind_stream {
KindStream::TCP => {
_ = client::remove_domain(self.tcp_stream.as_mut().unwrap(), domain)?;
client::read_response(self.tcp_stream.as_mut().unwrap())
}
KindStream::UNIX => {
_ = client::remove_domain(self.unix_stream.as_mut().unwrap(), domain)?;
client::read_response(self.unix_stream.as_mut().unwrap())
}
}
}
}
impl Drop for Controller {
fn drop(&mut self) {
match self.kind_stream {
KindStream::TCP => _ = client::close_connection(self.tcp_stream.as_mut().unwrap()),
KindStream::UNIX => _ = client::close_connection(self.unix_stream.as_mut().unwrap()),
}
}
}

View File

@@ -0,0 +1,2 @@
pub mod client;
pub mod controller;