add dns support

This commit is contained in:
2025-12-28 12:40:21 +00:00
parent 8adb7d560a
commit 35e6ff8140
11 changed files with 747 additions and 59 deletions

View File

@@ -1,3 +1,7 @@
use std::net::Ipv4Addr;
use std::str::FromStr;
use crate::api::error::ReturnedError;
use crate::config::{
docker::DockerConnectionConfig, mrproxy::MrproxyConnectionConfig, server::ServerConfig,
CONFIG_PATH,
@@ -5,8 +9,8 @@ use crate::config::{
use crate::controller::Controller;
use crate::deploy::container_options::Options;
use crate::deploy::starter;
use crate::{api::error::ReturnedError, config};
use actix_web::{delete, get, patch, put, web, App, HttpServer, Responder};
use dns_manager::ServerZonesConnection;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
@@ -57,7 +61,7 @@ async fn delete_container(
controller: web::Data<Controller>,
params: web::Query<ConainerStopParams>,
) -> Result<String, ReturnedError> {
match controller.delete_container(params.name.clone()).await {
match controller.delete_container_and_unbind(&params.name).await {
Ok(response) => Ok(response),
Err(e) => Err(ReturnedError {
name: e.to_string(),
@@ -77,12 +81,14 @@ async fn get_ip(
}
pub async fn start() -> std::io::Result<()> {
let server_config = ServerConfig::get_config(CONFIG_PATH).unwrap();
let controller = starter::start_docker(
DockerConnectionConfig::get_config(CONFIG_PATH).unwrap(),
MrproxyConnectionConfig::get_config(config::CONFIG_PATH).unwrap(),
MrproxyConnectionConfig::get_config(CONFIG_PATH).unwrap(),
ServerZonesConnection::get_config(CONFIG_PATH).unwrap(),
Ipv4Addr::from_str(&server_config.pub_addr).unwrap(),
)
.await;
let server_config = ServerConfig::get_config(CONFIG_PATH).unwrap();
let data = web::Data::new(controller);
HttpServer::new(move || {
App::new()
@@ -93,7 +99,7 @@ pub async fn start() -> std::io::Result<()> {
.service(delete_container)
.service(get_ip)
})
.bind((server_config.addr, server_config.port))?
.bind((server_config.linstening_addr, server_config.port))?
.run()
.await
}

View File

@@ -3,22 +3,34 @@ use std::{error::Error, fs::read_to_string};
use toml::Table;
pub struct ServerConfig {
pub addr: String,
pub pub_addr: String,
pub linstening_addr: String,
pub port: u16,
}
impl ServerConfig {
pub fn get_config(file_name: &str) -> Result<Self, Box<dyn Error>> {
let stored_file = read_to_string(file_name)?.parse::<Table>()?;
let addr = stored_file["server"]["addr"]
let pub_addr = stored_file["server"]["public_addr"]
.as_str()
.ok_or(generate_toml_parser_error_in_field("server addr"))?
.ok_or(generate_toml_parser_error_in_field("server public address"))?
.to_string();
let linstening_addr = stored_file["server"]["listening_addr"]
.as_str()
.ok_or(generate_toml_parser_error_in_field(
"server listening address",
))?
.to_string();
let port = stored_file["server"]["port"]
.as_integer()
.ok_or(generate_toml_parser_error_in_field("server port"))? as u16;
Ok(Self { addr, port })
Ok(Self {
pub_addr,
linstening_addr,
port,
})
}
}

View File

@@ -1,4 +1,4 @@
use crate::config::{docker::DockerConnectionConfig, mrproxy::MrproxyConnectionConfig};
use crate::config::mrproxy::MrproxyConnectionConfig;
use crate::database::exposer::MemStorage;
use crate::database::instance::Instance;
use crate::deploy::container::Container;
@@ -6,34 +6,39 @@ use crate::deploy::container_options::Options;
use crate::{deploy, mcproxy_client};
use bollard::errors::Error;
use bollard::Docker;
use log::error;
use dns_manager::{DnsManager, ServerZonesConnection};
use log::{error, warn};
use std::error::Error as GenericError;
use std::net::Ipv4Addr;
use std::sync::Mutex;
pub struct Controller {
driver: Docker,
pub_addr: Ipv4Addr,
network: String,
storage: Mutex<MemStorage>,
started: bool,
docker_config: DockerConnectionConfig,
dns_manager: DnsManager,
mrproxy_config: MrproxyConnectionConfig,
}
impl Controller {
pub async fn new(
driver: Docker,
pub_addr: Ipv4Addr,
network: String,
range: String,
docker_config: DockerConnectionConfig,
dns_config: ServerZonesConnection,
mrproxy_config: MrproxyConnectionConfig,
) -> Result<Self, bollard::errors::Error> {
) -> Result<Self, Box<dyn std::error::Error>> {
deploy::network::Network::new(driver.clone(), network.clone(), range).await?;
let cont = Self {
driver: driver,
pub_addr,
network: network,
storage: Mutex::new(MemStorage::new().unwrap()),
started: false,
docker_config,
dns_manager: DnsManager::new(dns_config)?,
mrproxy_config,
};
Ok(cont)
@@ -83,41 +88,39 @@ impl Controller {
.load_container(docker_id, domain.clone(), ip.clone(), image, ops)
.await
{
Ok(c) => {
match self
.bind_container_in_proxy(domain.clone(), ip, c.clone())
.await
{
Ok(_) => Ok(c),
Err(e) => {
error!("failed in the bind process with the proxy, deleting the container");
self.delete_container(domain).await?;
return Err(e);
}
Ok(c) => match self.bind_container_in_proxy(&domain, ip, &c).await {
Ok(_) => {
self.add_domain_to_dns(&domain).await?;
Ok(c)
}
}
Err(e) => {
error!("failed in the bind process with the proxy, deleting the container");
self.delete_container_and_unbind(&domain).await?;
return Err(e);
}
},
Err(e) => return Err(Box::new(e)),
}
}
async fn bind_container_in_proxy(
&self,
domain: String,
domain: &str,
ip: Option<String>,
container: Container,
container: &Container,
) -> Result<(), Box<dyn GenericError>> {
let ip_final = ip.unwrap_or(container.get_ip(&self.driver).await?);
log::debug!("ip binded: {}", ip_final);
let mut mrcp_controller =
mcproxy_client::controller::Controller::new(&self.mrproxy_config)?;
mrcp_controller.insert_new_domain(&domain, &ip_final)?;
mrcp_controller.insert_new_domain(&self.dns_manager.get_full_domain(domain), &ip_final)?;
Ok(())
}
async fn unbind_container_in_proxy(&self, domain: &str) -> Result<(), Box<dyn GenericError>> {
let mut mrcp_controller =
mcproxy_client::controller::Controller::new(&self.mrproxy_config)?;
mrcp_controller.remove_domain(&domain)?;
mrcp_controller.remove_domain(&self.dns_manager.get_full_domain(domain))?;
Ok(())
}
@@ -171,6 +174,7 @@ impl Controller {
.await
}
#[allow(dead_code)]
pub async fn is_started(&self) -> bool {
self.started
}
@@ -217,11 +221,21 @@ impl Controller {
}
}
pub async fn delete_container(&self, domain: String) -> Result<String, Box<dyn GenericError>> {
pub async fn delete_container_and_unbind(
&self,
domain: &str,
) -> Result<String, Box<dyn GenericError>> {
match self.storage.lock().unwrap().remove_instance(&domain) {
Some(data) => match data.1 {
Some(c) => {
self.unbind_container_in_proxy(&domain).await?;
let r_unbind = self.unbind_container_in_proxy(&domain).await;
if r_unbind.is_err() {
warn!("Error unbinding container {}", domain);
}
let r_del_domain = self.del_domain_to_dns(domain).await;
if r_del_domain.is_err() {
warn!("Error deleting domain {} from dns", domain);
}
self.prune_given_container(c).await
}
None => Ok(data.0.docker_id),
@@ -242,4 +256,14 @@ impl Controller {
.unwrap();
container.get_ip(&self.driver).await
}
pub async fn add_domain_to_dns(&self, domain: &str) -> Result<(), Box<dyn GenericError>> {
self.dns_manager.add_domain(domain, self.pub_addr).await?;
Ok(())
}
pub async fn del_domain_to_dns(&self, domain: &str) -> Result<(), Box<dyn GenericError>> {
self.dns_manager.del_domain(domain).await?;
Ok(())
}
}

View File

@@ -80,6 +80,7 @@ impl InstanceStorage {
Ok(rows.next()?.unwrap().get::<_, String>(0)?)
}
#[allow(dead_code)]
fn get_instance_id(&self, domain: &str) -> Result<Option<i64>> {
let mut stmt = self
.con

View File

@@ -7,5 +7,6 @@ pub struct Instance {
pub ip: Option<String>,
pub domain: String,
pub image: i64,
#[allow(dead_code)]
pub ops: Options,
}

View File

@@ -18,6 +18,7 @@ pub struct Container {
pub image: String,
pub net: String,
pub docker_id: Option<String>,
#[allow(dead_code)]
pub database_id: Option<i64>,
pub ops: Options,
}

View File

@@ -3,18 +3,12 @@ use bollard::models::{Ipam, IpamConfig, NetworkCreateRequest};
use bollard::query_parameters::ListNetworksOptions;
use std::collections::hash_map::HashMap;
pub struct Network {
name: String,
range: String,
}
pub struct Network {}
impl Network {
pub async fn new(docker: bollard::Docker, name: String, range: String) -> Result<Self, Error> {
if Self::check_network(docker.clone(), name.clone()).await {
Ok(Network {
name: name,
range: range,
})
Ok(Network {})
} else {
Self::create_network(docker, name, range).await
}
@@ -54,10 +48,7 @@ impl Network {
..Default::default()
};
match docker.create_network(create_network_options).await {
Ok(_n) => Ok(Network {
name: name,
range: range,
}),
Ok(_n) => Ok(Self {}),
Err(e) => Err(e),
}
}

View File

@@ -1,3 +1,5 @@
use std::net::Ipv4Addr;
use crate::{
config::{
docker::DockerConnectionConfig,
@@ -7,10 +9,13 @@ use crate::{
controller::Controller,
};
use bollard::{errors::Error, ClientVersion, Docker};
use dns_manager::ServerZonesConnection;
pub async fn start_docker(
docker_config: DockerConnectionConfig,
mrproxy_config: MrproxyConnectionConfig,
dns_config: ServerZonesConnection,
pub_addr: Ipv4Addr,
) -> Controller {
let docker = match generate_docker_connection(&docker_config) {
Ok(d) => d,
@@ -19,9 +24,10 @@ pub async fn start_docker(
env_logger::init_from_env(env_logger::Env::new().default_filter_or("debug"));
let controller = match Controller::new(
docker,
pub_addr,
docker_config.network_name.clone(),
docker_config.network_addr.clone(),
docker_config,
dns_config,
mrproxy_config,
)
.await