start refactor of ip management
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1 +1,3 @@
|
|||||||
/target/
|
/target/
|
||||||
|
/mdeploy.db
|
||||||
|
/mrdeploy_data/
|
||||||
|
|||||||
1690
Cargo.lock
generated
1690
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -4,14 +4,14 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bollard = "0.14"
|
bollard = "0.19"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
rusqlite = { version = "0.29.0", features = ["bundled"] }
|
rusqlite = { version = "0.29.0", features = ["bundled"] }
|
||||||
actix-web = "4"
|
actix-web = "4"
|
||||||
env_logger = "*"
|
env_logger = "0.11"
|
||||||
derive_more = "*"
|
derive_more = "*"
|
||||||
log = "*"
|
log = "0.4"
|
||||||
serde = "*"
|
serde = "*"
|
||||||
serde_json = "*"
|
serde_json = "*"
|
||||||
fallible-iterator = "*"
|
fallible-iterator = "*"
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use derive_more::{Display, Error};
|
use derive_more::{Display, Error};
|
||||||
|
|
||||||
impl actix_web::error::ResponseError for ReturnedError{}
|
impl actix_web::error::ResponseError for ReturnedError {}
|
||||||
|
|
||||||
#[derive(Debug, Display, Error)]
|
#[derive(Debug, Display, Error)]
|
||||||
#[display(fmt = "my error: {}", name)]
|
#[display("my error: {}", name)]
|
||||||
pub struct ReturnedError {
|
pub struct ReturnedError {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
use actix_web::{patch, put, delete, web, App, HttpServer, Responder};
|
|
||||||
use crate::api::error::ReturnedError;
|
use crate::api::error::ReturnedError;
|
||||||
use crate::controller::Controller;
|
use crate::controller::Controller;
|
||||||
use crate::deploy::starter;
|
|
||||||
use crate::deploy::container_options::Options;
|
use crate::deploy::container_options::Options;
|
||||||
|
use crate::deploy::starter;
|
||||||
|
use actix_web::{delete, get, patch, put, web, App, HttpServer, Responder};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
struct ConainerParams {
|
struct ConainerParams {
|
||||||
name: String,
|
name: String,
|
||||||
ip: String,
|
ip: Option<String>,
|
||||||
image: String,
|
image: String,
|
||||||
msg: Option<String>,
|
msg: Option<String>,
|
||||||
memory: Option<String>
|
memory: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
@@ -20,30 +20,58 @@ struct ConainerStopParams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[put("/container")]
|
#[put("/container")]
|
||||||
async fn create_container(controller: web::Data<Controller>,
|
async fn create_container(
|
||||||
params: web::Query<ConainerParams>) -> impl Responder {
|
controller: web::Data<Controller>,
|
||||||
|
params: web::Query<ConainerParams>,
|
||||||
|
) -> impl Responder {
|
||||||
let ops = Options::new(params.memory.clone(), params.msg.clone());
|
let ops = Options::new(params.memory.clone(), params.msg.clone());
|
||||||
controller.create_container(params.name.clone(), params.ip.clone(), params.image.clone(), ops).await
|
controller
|
||||||
|
.create_container(
|
||||||
|
params.name.clone(),
|
||||||
|
params.ip.clone(),
|
||||||
|
params.image.clone(),
|
||||||
|
ops,
|
||||||
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[patch("/container/stop")]
|
#[patch("/container/stop")]
|
||||||
async fn stop_container(controller: web::Data<Controller>,
|
async fn stop_container(
|
||||||
params: web::Query<ConainerStopParams>) -> Result<String, ReturnedError> {
|
controller: web::Data<Controller>,
|
||||||
|
params: web::Query<ConainerStopParams>,
|
||||||
|
) -> Result<String, ReturnedError> {
|
||||||
match controller.stop_container(params.name.clone()).await {
|
match controller.stop_container(params.name.clone()).await {
|
||||||
Ok(response) => Ok(response),
|
Ok(response) => Ok(response),
|
||||||
Err(e) => Err(ReturnedError { name: e.to_string()})
|
Err(e) => Err(ReturnedError {
|
||||||
|
name: e.to_string(),
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[delete("/container")]
|
#[delete("/container")]
|
||||||
async fn delete_container(controller: web::Data<Controller>,
|
async fn delete_container(
|
||||||
params: web::Query<ConainerStopParams>) -> Result<String, ReturnedError> {
|
controller: web::Data<Controller>,
|
||||||
|
params: web::Query<ConainerStopParams>,
|
||||||
|
) -> Result<String, ReturnedError> {
|
||||||
match controller.delete_container(params.name.clone()).await {
|
match controller.delete_container(params.name.clone()).await {
|
||||||
Ok(response) => Ok(response),
|
Ok(response) => Ok(response),
|
||||||
Err(e) => Err(ReturnedError { name: e.to_string()})
|
Err(e) => Err(ReturnedError {
|
||||||
|
name: e.to_string(),
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/container/{container_name}/ip")]
|
||||||
|
async fn get_ip(
|
||||||
|
controller: web::Data<Controller>,
|
||||||
|
container_name: web::Path<String>,
|
||||||
|
) -> Result<String, ReturnedError> {
|
||||||
|
Ok(controller
|
||||||
|
.get_ip(container_name.into_inner())
|
||||||
|
.await
|
||||||
|
.unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn start() -> std::io::Result<()> {
|
pub async fn start() -> std::io::Result<()> {
|
||||||
let controller = starter::start_docker().await;
|
let controller = starter::start_docker().await;
|
||||||
let data = web::Data::new(controller);
|
let data = web::Data::new(controller);
|
||||||
@@ -54,9 +82,9 @@ pub async fn start() -> std::io::Result<()> {
|
|||||||
.service(create_container)
|
.service(create_container)
|
||||||
.service(stop_container)
|
.service(stop_container)
|
||||||
.service(delete_container)
|
.service(delete_container)
|
||||||
|
.service(get_ip)
|
||||||
})
|
})
|
||||||
.bind(("127.0.0.1", 8080))?
|
.bind(("127.0.0.1", 8080))?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
use bollard::Docker;
|
|
||||||
use bollard::errors::Error;
|
|
||||||
use crate::deploy;
|
|
||||||
use crate::deploy::container::Container;
|
|
||||||
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_options::Options;
|
use crate::deploy::container_options::Options;
|
||||||
use std::sync::Mutex;
|
use bollard::errors::Error;
|
||||||
|
use bollard::Docker;
|
||||||
use log::error;
|
use log::error;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
pub struct Controller {
|
pub struct Controller {
|
||||||
driver: Docker,
|
driver: Docker,
|
||||||
@@ -16,7 +16,11 @@ pub struct Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Controller {
|
impl Controller {
|
||||||
pub async fn new(driver: Docker, network: String, range: String) -> Result<Self, bollard::errors::Error>{
|
pub async fn new(
|
||||||
|
driver: Docker,
|
||||||
|
network: String,
|
||||||
|
range: String,
|
||||||
|
) -> 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 {
|
||||||
driver: driver,
|
driver: driver,
|
||||||
@@ -27,60 +31,86 @@ impl Controller {
|
|||||||
Ok(cont)
|
Ok(cont)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_container(&self, domain: String, ip: String, image: String, ops: Options) -> String {
|
pub async fn create_container(
|
||||||
|
&self,
|
||||||
|
domain: String,
|
||||||
|
ip: Option<String>,
|
||||||
|
image: String,
|
||||||
|
ops: Options,
|
||||||
|
) -> 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) => 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.load_container(None,domain.clone(),ip.clone(),image.clone(),ops).await {
|
match self
|
||||||
|
.load_container(None, domain.clone(), ip.clone(), image.clone(), ops)
|
||||||
|
.await
|
||||||
|
{
|
||||||
Ok(c) => {
|
Ok(c) => {
|
||||||
self.storage.try_lock().unwrap().new_instance(c.clone()).unwrap();
|
self.storage
|
||||||
|
.try_lock()
|
||||||
|
.unwrap()
|
||||||
|
.new_instance(c.clone())
|
||||||
|
.unwrap();
|
||||||
c.get_id()
|
c.get_id()
|
||||||
},
|
}
|
||||||
Err(_e) => "error creating container".to_string(),
|
Err(e) => format!("error creating container: {}", e.to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn start_container_from_instance(&self, instance: Instance) {
|
pub async fn start_container_from_instance(&self, instance: Instance) {
|
||||||
let image = match self.storage.lock().unwrap().id_to_image(instance.image.clone()) {
|
let image = match self
|
||||||
|
.storage
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.id_to_image(instance.image.clone())
|
||||||
|
{
|
||||||
Ok(i) => i,
|
Ok(i) => i,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("image not found: {}", e);
|
error!("image not found: {}", e);
|
||||||
return
|
return;
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
match self.load_container(
|
match self
|
||||||
Some(instance.docker_id.clone()),
|
.load_container(
|
||||||
instance.domain.clone(),
|
Some(instance.docker_id.clone()),
|
||||||
instance.ip.clone(),
|
instance.domain.clone(),
|
||||||
image,
|
instance.ip.clone(),
|
||||||
Options::new(None, None)).await {
|
image,
|
||||||
|
Options::new(None, None),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
Ok(c) => {
|
Ok(c) => {
|
||||||
self.storage.lock().unwrap().loaded_instance(instance, c);
|
self.storage.lock().unwrap().loaded_instance(instance, c);
|
||||||
},
|
}
|
||||||
Err(e) => error!("{}",e),
|
Err(e) => error!("{}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn load_container(&self, docker_id: Option<String>,
|
async fn load_container(
|
||||||
domain: String,
|
&self,
|
||||||
ip: String,
|
docker_id: Option<String>,
|
||||||
image: String,
|
domain: String,
|
||||||
ops: Options) -> Result<deploy::container::Container,
|
ip: Option<String>,
|
||||||
bollard::errors::Error>
|
image: String,
|
||||||
{
|
ops: Options,
|
||||||
deploy::container::Container::new(self.driver.clone(),
|
) -> Result<deploy::container::Container, bollard::errors::Error> {
|
||||||
docker_id,
|
deploy::container::Container::new(
|
||||||
domain,
|
self.driver.clone(),
|
||||||
ip,
|
docker_id,
|
||||||
image,
|
domain,
|
||||||
self.network.clone(),
|
ip,
|
||||||
ops).await
|
image,
|
||||||
|
self.network.clone(),
|
||||||
|
ops,
|
||||||
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn is_started(&self) -> bool {
|
pub async fn is_started(&self) -> bool {
|
||||||
@@ -91,9 +121,9 @@ impl Controller {
|
|||||||
let data = match self.storage.lock().unwrap().get_instances_db() {
|
let data = match self.storage.lock().unwrap().get_instances_db() {
|
||||||
Ok(d) => d,
|
Ok(d) => d,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("instances can't be loaded: {}",e);
|
error!("instances can't be loaded: {}", e);
|
||||||
return false
|
return false;
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
println!("instances {}", data.len());
|
println!("instances {}", data.len());
|
||||||
for instance in data {
|
for instance in data {
|
||||||
@@ -102,14 +132,14 @@ impl Controller {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn stop_given_container(&self, container:Container) -> Result<String, Error> {
|
async fn stop_given_container(&self, container: Container) -> Result<String, Error> {
|
||||||
match container.stop(&self.driver).await {
|
match container.stop(&self.driver).await {
|
||||||
Ok(_i) => Ok(container.get_id()),
|
Ok(_i) => Ok(container.get_id()),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn prune_given_container(&self, container:Container) -> Result<String, Error> {
|
async fn prune_given_container(&self, container: Container) -> Result<String, Error> {
|
||||||
match container.remove(&self.driver).await {
|
match container.remove(&self.driver).await {
|
||||||
Ok(_i) => Ok(container.get_id()),
|
Ok(_i) => Ok(container.get_id()),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
@@ -118,30 +148,34 @@ impl Controller {
|
|||||||
|
|
||||||
pub async fn stop_container(&self, domain: String) -> Result<String, Error> {
|
pub async fn stop_container(&self, domain: String) -> Result<String, Error> {
|
||||||
match self.storage.lock().unwrap().stop_instance(domain) {
|
match self.storage.lock().unwrap().stop_instance(domain) {
|
||||||
Some(c) => {
|
Some(c) => self.stop_given_container(c).await,
|
||||||
self.stop_given_container(c).await
|
|
||||||
},
|
|
||||||
None => Err(Error::DockerResponseServerError {
|
None => Err(Error::DockerResponseServerError {
|
||||||
status_code: 404, message: "container not found".to_string()
|
status_code: 404,
|
||||||
}),
|
message: "container not found".to_string(),
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn delete_container(&self, domain: String) -> Result<String, Error> {
|
pub async fn delete_container(&self, domain: String) -> Result<String, Error> {
|
||||||
match self.storage.lock().unwrap().remove_instance(domain) {
|
match self.storage.lock().unwrap().remove_instance(domain) {
|
||||||
Some(data) => {
|
Some(data) => match data.1 {
|
||||||
match data.1 {
|
Some(c) => self.prune_given_container(c).await,
|
||||||
Some(c) => self.prune_given_container(c).await,
|
None => Ok(data.0.docker_id),
|
||||||
None => Ok(data.0.docker_id),
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
None => Err(Error::DockerResponseServerError {
|
None => Err(Error::DockerResponseServerError {
|
||||||
status_code: 404, message: "container not found".to_string()
|
status_code: 404,
|
||||||
}),
|
message: "container not found".to_string(),
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_ip(&self, domain: String) -> Result<String, Error> {
|
||||||
|
let container = self
|
||||||
|
.storage
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.search_instance(domain.clone())
|
||||||
|
.unwrap();
|
||||||
|
container.get_ip(&self.driver).await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
use rusqlite::{Connection, Result};
|
|
||||||
use fallible_iterator::FallibleIterator;
|
|
||||||
use crate::database::instance::Instance;
|
use crate::database::instance::Instance;
|
||||||
use crate::deploy::container_options::Options;
|
use crate::deploy::container_options::Options;
|
||||||
|
use fallible_iterator::FallibleIterator;
|
||||||
|
use rusqlite::{types::Null, Connection, Result};
|
||||||
|
|
||||||
const PATH: &str = "mdeploy.db";
|
const PATH: &str = "mdeploy.db";
|
||||||
|
|
||||||
pub struct ConfServer{
|
pub struct ConfServer {
|
||||||
ip: String,
|
ip: String,
|
||||||
port: String,
|
port: String,
|
||||||
ip_top_limit: u8,
|
ip_top_limit: u8,
|
||||||
@@ -19,9 +19,7 @@ pub struct InstanceStorage {
|
|||||||
impl InstanceStorage {
|
impl InstanceStorage {
|
||||||
pub fn new() -> Result<Self> {
|
pub fn new() -> Result<Self> {
|
||||||
let con = Connection::open(PATH)?;
|
let con = Connection::open(PATH)?;
|
||||||
let ret = Self {
|
let ret = Self { con: con };
|
||||||
con : con,
|
|
||||||
};
|
|
||||||
ret.create_table()?;
|
ret.create_table()?;
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
@@ -39,36 +37,42 @@ impl InstanceStorage {
|
|||||||
options TEXT,
|
options TEXT,
|
||||||
image INTEGER,
|
image INTEGER,
|
||||||
FOREIGN KEY(image) REFERENCES images(id));
|
FOREIGN KEY(image) REFERENCES images(id));
|
||||||
COMMIT;"
|
COMMIT;",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_image(&self, image: String) -> Result<()>{
|
fn insert_image(&self, image: &str) -> Result<()> {
|
||||||
let mut stmt = self.con.prepare("INSERT INTO images(name) values(?1)")?;
|
let mut stmt = self.con.prepare("INSERT INTO images(name) values(?1)")?;
|
||||||
stmt.execute([image])?;
|
stmt.execute([image])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_instances(&mut self) -> Result<Vec<Instance>> {
|
pub fn load_instances(&mut self) -> Result<Vec<Instance>> {
|
||||||
let mut stmt = self.con.prepare("select id, docker_id, ip, domain, options, image from l_instances")?;
|
let mut stmt = self
|
||||||
let mut rows = stmt.query([])?;
|
.con
|
||||||
rows.map(|r| Ok(Instance{
|
.prepare("select id, docker_id, ip, domain, options, image from l_instances")?;
|
||||||
id: r.get::<_, i64>(0)?,
|
let rows = stmt.query([])?;
|
||||||
docker_id: r.get::<_, String>(1)?,
|
rows.map(|r| {
|
||||||
ip: r.get::<_, String>(2)?,
|
Ok(Instance {
|
||||||
domain: r.get::<_, String>(3)?,
|
id: r.get::<_, i64>(0)?,
|
||||||
ops: Options::new_from_json(r.get::<_, String>(4)?),
|
docker_id: r.get::<_, String>(1)?,
|
||||||
image: r.get::<_, i64>(5)?,
|
ip: r.get::<_, String>(2).ok(),
|
||||||
})).collect()
|
domain: r.get::<_, String>(3)?,
|
||||||
|
ops: Options::new_from_json(r.get::<_, String>(4)?),
|
||||||
|
image: r.get::<_, i64>(5)?,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_images(&mut self) -> Result<Vec<(String, i64)>> {
|
pub fn load_images(&mut self) -> Result<Vec<(String, i64)>> {
|
||||||
let mut stmt = self.con.prepare("select id, name from images")?;
|
let mut stmt = self.con.prepare("select id, name from images")?;
|
||||||
let mut rows = stmt.query([])?;
|
let rows = stmt.query([])?;
|
||||||
rows.map(|row| Ok((row.get::<_, String>(1)?, row.get::<_, i64>(0)?))).collect()
|
rows.map(|row| Ok((row.get::<_, String>(1)?, row.get::<_, i64>(0)?)))
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_image_id(&self, image: String) -> Result<Option<i64>> {
|
fn get_image_id(&self, image: &str) -> Result<Option<i64>> {
|
||||||
let mut stmt = self.con.prepare("select id from images where name = ?1")?;
|
let mut stmt = self.con.prepare("select id from images where name = ?1")?;
|
||||||
let mut rows = stmt.query([image])?;
|
let mut rows = stmt.query([image])?;
|
||||||
Ok(match rows.next()? {
|
Ok(match rows.next()? {
|
||||||
@@ -83,8 +87,10 @@ impl InstanceStorage {
|
|||||||
Ok(rows.next()?.unwrap().get::<_, String>(0)?)
|
Ok(rows.next()?.unwrap().get::<_, String>(0)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_instance_id(&self, domain: String) -> Result<Option<i64>> {
|
fn get_instance_id(&self, domain: &str) -> Result<Option<i64>> {
|
||||||
let mut stmt = self.con.prepare("select id from l_instances where domain = ?1")?;
|
let mut stmt = self
|
||||||
|
.con
|
||||||
|
.prepare("select id from l_instances where domain = ?1")?;
|
||||||
let mut rows = stmt.query([domain])?;
|
let mut rows = stmt.query([domain])?;
|
||||||
Ok(match rows.next()? {
|
Ok(match rows.next()? {
|
||||||
Some(i) => Some(i.get::<_, i64>(0)?),
|
Some(i) => Some(i.get::<_, i64>(0)?),
|
||||||
@@ -92,14 +98,23 @@ impl InstanceStorage {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_instance(&mut self, docker_id: String, ip: String, domain: String, ops: Options, image: i64) -> Result<Instance>{
|
pub fn new_instance(
|
||||||
|
&mut self,
|
||||||
|
docker_id: String,
|
||||||
|
ip: Option<String>,
|
||||||
|
domain: String,
|
||||||
|
ops: Options,
|
||||||
|
image: i64,
|
||||||
|
) -> Result<Instance> {
|
||||||
//let image_id = self.create_or_get_image_id(image.clone(), 0)?;
|
//let image_id = self.create_or_get_image_id(image.clone(), 0)?;
|
||||||
let mut stmt = self.con.prepare("INSERT INTO l_instances(docker_id, ip, domain, options, image) values(?1, ?2, ?3, ?4, ?5)")?;
|
let mut stmt = self.con.prepare("INSERT INTO l_instances(docker_id, ip, domain, options, image) values(?1, ?2, ?3, ?4, ?5)")?;
|
||||||
stmt.execute([docker_id.clone(),
|
stmt.execute([
|
||||||
ip.clone(),
|
Some(docker_id.clone()),
|
||||||
domain.clone(),
|
ip.clone(),
|
||||||
ops.to_json(),
|
Some(domain.clone()),
|
||||||
image.to_string()])?;
|
Some(ops.to_json()),
|
||||||
|
Some(image.to_string()),
|
||||||
|
])?;
|
||||||
Ok(Instance {
|
Ok(Instance {
|
||||||
id: image,
|
id: image,
|
||||||
docker_id: docker_id,
|
docker_id: docker_id,
|
||||||
@@ -110,31 +125,30 @@ impl InstanceStorage {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_instance(&mut self, id: String) -> Result<usize> {
|
pub fn remove_instance(&mut self, id: &str) -> Result<usize> {
|
||||||
let mut stmt = self.con.prepare("DELETE from l_instances where id=?1")?;
|
let mut stmt = self.con.prepare("DELETE from l_instances where id=?1")?;
|
||||||
stmt.execute([id])
|
stmt.execute([id])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn image_to_id(&self, image: String) -> Result<i64> {
|
pub fn image_to_id(&self, image: &str) -> Result<i64> {
|
||||||
self.create_or_get_image_id(image, 0)
|
self.create_or_get_image_id(image, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_or_get_image_id(&self, image: String, mut depth: i64) -> Result<i64> {
|
fn create_or_get_image_id(&self, image: &str, mut depth: i64) -> Result<i64> {
|
||||||
if depth > 1 {
|
if depth > 1 {
|
||||||
return Err(rusqlite::Error::QueryReturnedNoRows);
|
return Err(rusqlite::Error::QueryReturnedNoRows);
|
||||||
}
|
}
|
||||||
depth+=1;
|
depth += 1;
|
||||||
match self.get_image_id(image.clone()) {
|
match self.get_image_id(image) {
|
||||||
Ok(Some(id)) => Ok(id),
|
Ok(Some(id)) => Ok(id),
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
self.insert_image(image.clone())?;
|
self.insert_image(image)?;
|
||||||
self.create_or_get_image_id(image, depth)
|
self.create_or_get_image_id(image, depth)
|
||||||
}
|
}
|
||||||
Err(_e) => {
|
Err(_e) => {
|
||||||
self.insert_image(image.clone())?;
|
self.insert_image(image)?;
|
||||||
self.create_or_get_image_id(image, depth)
|
self.create_or_get_image_id(image, depth)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use std::collections::hash_map::HashMap;
|
|
||||||
use rusqlite::Error;
|
|
||||||
use crate::deploy::container::Container;
|
|
||||||
use crate::database::direct_access::InstanceStorage;
|
use crate::database::direct_access::InstanceStorage;
|
||||||
use crate::database::instance::Instance;
|
use crate::database::instance::Instance;
|
||||||
|
use crate::deploy::container::Container;
|
||||||
|
use rusqlite::Error;
|
||||||
|
use std::collections::hash_map::HashMap;
|
||||||
|
|
||||||
pub struct MemStorage {
|
pub struct MemStorage {
|
||||||
containers: Vec<(Instance, Option<Container>)>,
|
containers: Vec<(Instance, Option<Container>)>,
|
||||||
@@ -13,46 +13,51 @@ pub struct MemStorage {
|
|||||||
impl MemStorage {
|
impl MemStorage {
|
||||||
pub fn new() -> Result<Self, Error> {
|
pub fn new() -> Result<Self, Error> {
|
||||||
let mut storage = InstanceStorage::new()?;
|
let mut storage = InstanceStorage::new()?;
|
||||||
let images = storage.load_images()?
|
let images = storage
|
||||||
.into_iter().map(|image|(image.0, image.1))
|
.load_images()?
|
||||||
.collect::<HashMap<_, _>>();
|
.into_iter()
|
||||||
Ok(Self{
|
.map(|image| (image.0, image.1))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
Ok(Self {
|
||||||
containers: Vec::new(),
|
containers: Vec::new(),
|
||||||
images: images,
|
images: images,
|
||||||
storage: storage,
|
storage: storage,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn image_to_id(&mut self, image: String) -> Result<i64, Error> {
|
fn image_to_id(&mut self, image: &str) -> Result<i64, Error> {
|
||||||
match self.images.get(&mut image.clone()) {
|
match self.images.get(image) {
|
||||||
Some(id) => Ok(*id),
|
Some(id) => Ok(*id),
|
||||||
None => {
|
None => {
|
||||||
let id = self.storage.image_to_id(image.clone())?;
|
let id = self.storage.image_to_id(image)?;
|
||||||
self.images.insert(image, id.clone());
|
self.images.insert(image.to_string(), id.clone());
|
||||||
Ok(id)
|
Ok(id)
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn id_to_image(&mut self, image: i64) -> Result<String, Error>{
|
pub fn id_to_image(&mut self, image: i64) -> Result<String, Error> {
|
||||||
self.storage.get_image_name(image)
|
self.storage.get_image_name(image)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_instance(&mut self, container: Container) -> Result<(), Error> {
|
pub fn new_instance(&mut self, container: Container) -> Result<(), Error> {
|
||||||
let image_id = self.image_to_id(container.image.clone())?;
|
let image_id = self.image_to_id(&container.image)?;
|
||||||
let ins = self.storage.new_instance(
|
let ins = self.storage.new_instance(
|
||||||
container.get_id(),
|
container.get_id(),
|
||||||
container.ip.clone(),
|
container.ip.clone(),
|
||||||
container.name.clone(),
|
container.name.clone(),
|
||||||
container.ops.clone(),
|
container.ops.clone(),
|
||||||
image_id)?;
|
image_id,
|
||||||
|
)?;
|
||||||
self.containers.push((ins, Some(container)));
|
self.containers.push((ins, Some(container)));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn search_instance(&self, name: String) -> Option<Container> {
|
pub fn search_instance(&self, name: String) -> Option<Container> {
|
||||||
for cont in &self.containers {
|
for cont in &self.containers {
|
||||||
if cont.0.domain == name { return cont.1.clone(); }
|
if cont.0.domain == name {
|
||||||
|
return cont.1.clone();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@@ -71,11 +76,11 @@ impl MemStorage {
|
|||||||
match self.containers.get(i) {
|
match self.containers.get(i) {
|
||||||
Some(c) => {
|
Some(c) => {
|
||||||
if c.0.domain == name {
|
if c.0.domain == name {
|
||||||
self.storage.remove_instance(c.0.id.to_string().clone());
|
_ = self.storage.remove_instance(&c.0.id.to_string());
|
||||||
return Some(self.containers.remove(i));
|
return Some(self.containers.remove(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => break
|
None => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
@@ -88,5 +93,4 @@ impl MemStorage {
|
|||||||
pub fn get_instances_db(&mut self) -> Result<Vec<Instance>, Error> {
|
pub fn get_instances_db(&mut self) -> Result<Vec<Instance>, Error> {
|
||||||
self.storage.load_instances()
|
self.storage.load_instances()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ use crate::deploy::container_options::Options;
|
|||||||
pub struct Instance {
|
pub struct Instance {
|
||||||
pub id: i64,
|
pub id: i64,
|
||||||
pub docker_id: String,
|
pub docker_id: String,
|
||||||
pub ip: String,
|
pub ip: Option<String>,
|
||||||
pub domain: String,
|
pub domain: String,
|
||||||
pub image: i64,
|
pub image: i64,
|
||||||
pub ops: Options,
|
pub ops: Options,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
|
use std::fs::{canonicalize, create_dir};
|
||||||
use std::vec;
|
use std::vec;
|
||||||
use std::fs::{create_dir, canonicalize};
|
|
||||||
|
|
||||||
const BASE_PATH : &str = "mrdeploy_data/";
|
const BASE_PATH: &str = "mrdeploy_data/";
|
||||||
|
|
||||||
pub fn generate_bindpaths(mut name: String) -> Vec<String>{
|
pub fn generate_bindpaths(mut name: String) -> Vec<String> {
|
||||||
name.insert_str(0,BASE_PATH);
|
name.insert_str(0, BASE_PATH);
|
||||||
let path = match canonicalize(name.clone()) {
|
let path = match canonicalize(name.clone()) {
|
||||||
Ok(p) => String::from(p.to_str().unwrap()),
|
Ok(p) => String::from(p.to_str().unwrap()),
|
||||||
Err(_e) => name,
|
Err(_e) => name,
|
||||||
@@ -13,6 +13,6 @@ pub fn generate_bindpaths(mut name: String) -> Vec<String>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_fs(mut name: String) -> Result<(), std::io::Error> {
|
pub fn check_fs(mut name: String) -> Result<(), std::io::Error> {
|
||||||
name.insert_str(0,BASE_PATH);
|
name.insert_str(0, BASE_PATH);
|
||||||
create_dir(name)
|
create_dir(name)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,21 @@
|
|||||||
use bollard::container::{StartContainerOptions,
|
|
||||||
StopContainerOptions,
|
|
||||||
CreateContainerOptions,
|
|
||||||
RemoveContainerOptions,
|
|
||||||
Config,
|
|
||||||
NetworkingConfig,
|
|
||||||
ListContainersOptions};
|
|
||||||
use bollard::models::{EndpointSettings, EndpointIpamConfig, HostConfig};
|
|
||||||
use bollard::errors::{Error, Error::IOError};
|
|
||||||
use std::io::ErrorKind::AlreadyExists;
|
|
||||||
use std::collections::hash_map::HashMap;
|
|
||||||
use crate::deploy::bind;
|
use crate::deploy::bind;
|
||||||
use crate::deploy::container_options::Options;
|
use crate::deploy::container_options::Options;
|
||||||
|
//use bollard::container::InspectContainerOptions;
|
||||||
|
use bollard::errors::{Error, Error::IOError};
|
||||||
|
use bollard::models::{EndpointIpamConfig, EndpointSettings, HostConfig, NetworkingConfig};
|
||||||
|
use bollard::query_parameters::{
|
||||||
|
CreateContainerOptions, InspectContainerOptions, InspectContainerOptionsBuilder,
|
||||||
|
ListContainersOptions, RemoveContainerOptions, StartContainerOptions, StopContainerOptions,
|
||||||
|
};
|
||||||
|
use bollard::secret::ContainerCreateBody;
|
||||||
|
use std::collections::hash_map::HashMap;
|
||||||
|
use std::io::ErrorKind::AlreadyExists;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Container {
|
pub struct Container {
|
||||||
pub name: String, //Must be the domain name
|
pub name: String, //Must be the domain name
|
||||||
pub start: bool,
|
pub start: bool,
|
||||||
pub ip: String,
|
pub ip: Option<String>,
|
||||||
pub image: String,
|
pub image: String,
|
||||||
pub net: String,
|
pub net: String,
|
||||||
pub docker_id: Option<String>,
|
pub docker_id: Option<String>,
|
||||||
@@ -25,14 +24,15 @@ pub struct Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Container {
|
impl Container {
|
||||||
pub async fn new(docker: bollard::Docker,
|
pub async fn new(
|
||||||
docker_id: Option<String>,
|
docker: bollard::Docker,
|
||||||
name: String,
|
docker_id: Option<String>,
|
||||||
ip: String,
|
name: String,
|
||||||
image: String,
|
ip: Option<String>,
|
||||||
net: String,
|
image: String,
|
||||||
ops: Options) -> Result<Container, Error> {
|
net: String,
|
||||||
|
ops: Options,
|
||||||
|
) -> Result<Container, Error> {
|
||||||
let mut container = Container {
|
let mut container = Container {
|
||||||
name: name,
|
name: name,
|
||||||
ip: ip,
|
ip: ip,
|
||||||
@@ -44,15 +44,15 @@ impl Container {
|
|||||||
ops: ops,
|
ops: ops,
|
||||||
};
|
};
|
||||||
match container.start(docker).await {
|
match container.start(docker).await {
|
||||||
Ok(c) => {
|
Ok(_c) => {
|
||||||
container.start=true;
|
container.start = true;
|
||||||
Ok(container)
|
Ok(container)
|
||||||
}
|
}
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn start(&mut self, docker: bollard::Docker) -> Result<bool, Error>{
|
async fn start(&mut self, docker: bollard::Docker) -> Result<bool, Error> {
|
||||||
match bind::check_fs(self.name.clone()) {
|
match bind::check_fs(self.name.clone()) {
|
||||||
Ok(_r) => (),
|
Ok(_r) => (),
|
||||||
Err(ref e) if e.kind() == AlreadyExists => (),
|
Err(ref e) if e.kind() == AlreadyExists => (),
|
||||||
@@ -60,23 +60,32 @@ impl Container {
|
|||||||
}
|
}
|
||||||
let ret = match self.exist_container(docker.clone()).await? {
|
let ret = match self.exist_container(docker.clone()).await? {
|
||||||
Some(id) => {
|
Some(id) => {
|
||||||
self.docker_id=Some(id);
|
self.docker_id = Some(id);
|
||||||
true
|
true
|
||||||
},
|
}
|
||||||
None => {
|
None => {
|
||||||
log::info!("creating container with name: {}", self.name);
|
log::info!("creating container with name: {}", self.name);
|
||||||
self.docker_id = Some(docker.create_container(Some(
|
self.docker_id = Some(
|
||||||
create_options(self.name.clone())),
|
docker
|
||||||
create_config(self.name.clone(),
|
.create_container(
|
||||||
self.ip.clone(),
|
Some(create_options(self.name.clone())),
|
||||||
self.net.clone(),
|
create_config(
|
||||||
self.image.clone(),
|
self.name.clone(),
|
||||||
self.ops.clone()))
|
self.ip.clone(),
|
||||||
.await?.id);
|
self.net.clone(),
|
||||||
false
|
self.image.clone(),
|
||||||
},
|
self.ops.clone(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
.id,
|
||||||
|
);
|
||||||
|
false
|
||||||
|
}
|
||||||
};
|
};
|
||||||
docker.start_container(&self.name, None::<StartContainerOptions<String>>).await?;
|
docker
|
||||||
|
.start_container(&self.name, None::<StartContainerOptions>)
|
||||||
|
.await?;
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,9 +97,9 @@ impl Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn exist_container(&self, docker: bollard::Docker) -> Result<Option<String>, Error> {
|
async fn exist_container(&self, docker: bollard::Docker) -> Result<Option<String>, Error> {
|
||||||
let list = docker.list_containers(
|
let list = docker
|
||||||
Some(create_search_container(self.name.clone()))
|
.list_containers(Some(create_search_container(self.name.clone())))
|
||||||
).await?;
|
.await?;
|
||||||
let mut comparable_name = self.name.clone();
|
let mut comparable_name = self.name.clone();
|
||||||
comparable_name.insert_str(0, "/");
|
comparable_name.insert_str(0, "/");
|
||||||
for cs in list {
|
for cs in list {
|
||||||
@@ -101,7 +110,7 @@ impl Container {
|
|||||||
return Ok(cs.id.clone());
|
return Ok(cs.id.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
None => (),
|
None => (),
|
||||||
}
|
}
|
||||||
@@ -109,43 +118,77 @@ impl Container {
|
|||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn stop(&self, docker: &bollard::Docker) -> Result<(), Error>{
|
pub async fn stop(&self, docker: &bollard::Docker) -> Result<(), Error> {
|
||||||
docker.stop_container(self.name.as_str(), Some(create_stop_options())).await
|
docker
|
||||||
|
.stop_container(self.name.as_str(), Some(create_stop_options()))
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn remove(&self, docker: &bollard::Docker) -> Result<String, Error> {
|
pub async fn remove(&self, docker: &bollard::Docker) -> Result<String, Error> {
|
||||||
docker.remove_container(self.get_id().as_str(), Some(create_remove_option())).await?;
|
docker
|
||||||
|
.remove_container(self.get_id().as_str(), Some(create_remove_option()))
|
||||||
|
.await?;
|
||||||
Ok(self.docker_id.clone().unwrap())
|
Ok(self.docker_id.clone().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_ip(&self, docker: &bollard::Docker) -> Result<String, Error> {
|
||||||
|
match &self.ip {
|
||||||
|
Some(ip) => Ok(ip.clone()),
|
||||||
|
None => {
|
||||||
|
let response = docker
|
||||||
|
.inspect_container(
|
||||||
|
&self.name,
|
||||||
|
Some(InspectContainerOptionsBuilder::new().size(true).build()),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
let ns = response.network_settings.unwrap().networks.unwrap();
|
||||||
|
|
||||||
|
let ip = ns.into_values().next().unwrap().ip_address.unwrap();
|
||||||
|
|
||||||
|
//let ip =
|
||||||
|
//let b_ns = ns.is_some();
|
||||||
|
|
||||||
|
//let ip = ns.unwrap().ip_address.unwrap();
|
||||||
|
//log::debug!("network settings: {}, ip address: {}", b_ns, ip);
|
||||||
|
Ok(ip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_search_container(name: String) -> ListContainersOptions<String> {
|
fn create_search_container(name: String) -> ListContainersOptions {
|
||||||
let mut filters = HashMap::new();
|
let mut filters = HashMap::new();
|
||||||
filters.insert("name".to_string(), vec![name]);
|
filters.insert("name".to_string(), vec![name]);
|
||||||
|
|
||||||
ListContainersOptions{
|
ListContainersOptions {
|
||||||
all: true,
|
all: true,
|
||||||
filters,
|
filters: Some(filters),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_config(name: String, ip: String, net: String, image: String, ops: Options) -> Config<String> {
|
fn create_config(
|
||||||
|
name: String,
|
||||||
|
ip: Option<String>,
|
||||||
|
net: String,
|
||||||
|
image: String,
|
||||||
|
ops: Options,
|
||||||
|
) -> ContainerCreateBody {
|
||||||
let endpoint = EndpointSettings {
|
let endpoint = EndpointSettings {
|
||||||
ipam_config: Some(EndpointIpamConfig{
|
ipam_config: Some(EndpointIpamConfig {
|
||||||
ipv4_address: Some(ip),
|
ipv4_address: ip,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let mut hash = HashMap::new();
|
let mut hash = HashMap::new();
|
||||||
hash.insert(net, endpoint);
|
hash.insert(net, endpoint);
|
||||||
let net = NetworkingConfig {
|
let net = NetworkingConfig {
|
||||||
endpoints_config: hash
|
endpoints_config: Some(hash),
|
||||||
};
|
};
|
||||||
let mut env = vec!["EULA=TRUE".to_string()];
|
let mut env = vec!["EULA=TRUE".to_string()];
|
||||||
env.append(&mut ops.generate_config());
|
env.append(&mut ops.generate_config());
|
||||||
Config {
|
ContainerCreateBody {
|
||||||
image: Some(image),
|
image: Some(image),
|
||||||
env: Some(env),
|
env: Some(env),
|
||||||
host_config: Some(create_hostconfig(name)),
|
host_config: Some(create_hostconfig(name)),
|
||||||
@@ -161,21 +204,22 @@ fn create_hostconfig(name: String) -> HostConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_options(name: String) -> CreateContainerOptions<String> {
|
fn create_options(name: String) -> CreateContainerOptions {
|
||||||
CreateContainerOptions{
|
CreateContainerOptions {
|
||||||
name: name,
|
name: Some(name),
|
||||||
platform: None,
|
platform: "".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_stop_options() -> StopContainerOptions {
|
fn create_stop_options() -> StopContainerOptions {
|
||||||
StopContainerOptions {
|
StopContainerOptions {
|
||||||
t: 30,
|
signal: None,
|
||||||
|
t: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_remove_option() -> RemoveContainerOptions {
|
fn create_remove_option() -> RemoveContainerOptions {
|
||||||
RemoveContainerOptions{
|
RemoveContainerOptions {
|
||||||
force: true,
|
force: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
use bollard::errors::Error;
|
use bollard::errors::Error;
|
||||||
use bollard::errors::Error::DockerResponseServerError;
|
use bollard::models::{Ipam, IpamConfig, NetworkCreateRequest};
|
||||||
use bollard::models::{IpamConfig,Ipam};
|
use bollard::query_parameters::ListNetworksOptions;
|
||||||
use bollard::network::{CreateNetworkOptions, ListNetworksOptions};
|
|
||||||
use std::collections::hash_map::HashMap;
|
use std::collections::hash_map::HashMap;
|
||||||
|
|
||||||
pub struct Network {
|
pub struct Network {
|
||||||
name: String,
|
name: String,
|
||||||
range: String,
|
range: String,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Network {
|
impl Network {
|
||||||
@@ -24,37 +22,43 @@ impl Network {
|
|||||||
|
|
||||||
async fn check_network(docker: bollard::Docker, name: String) -> bool {
|
async fn check_network(docker: bollard::Docker, name: String) -> bool {
|
||||||
let mut list_networks_filters = HashMap::new();
|
let mut list_networks_filters = HashMap::new();
|
||||||
list_networks_filters.insert("name", vec![name.as_str()]);
|
list_networks_filters.insert("name".to_string(), vec![name]);
|
||||||
match docker.list_networks(Some(ListNetworksOptions {
|
match docker
|
||||||
filters: list_networks_filters,
|
.list_networks(Some(ListNetworksOptions {
|
||||||
})).await {
|
filters: Some(list_networks_filters),
|
||||||
Ok(l)=> l.len()>0,
|
}))
|
||||||
Err(e)=> false
|
.await
|
||||||
|
{
|
||||||
|
Ok(l) => l.len() > 0,
|
||||||
|
Err(_e) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_network(docker: bollard::Docker, name: String, range: String) -> Result<Self, Error>{
|
async fn create_network(
|
||||||
|
docker: bollard::Docker,
|
||||||
|
name: String,
|
||||||
|
range: String,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
let ipam_config = IpamConfig {
|
let ipam_config = IpamConfig {
|
||||||
subnet: Some(range.clone()),
|
subnet: Some(range.clone()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let create_network_options = CreateNetworkOptions {
|
let create_network_options = NetworkCreateRequest {
|
||||||
name: name.as_str(),
|
name: name.clone(),
|
||||||
driver: "bridge",
|
driver: Some("bridge".to_string()),
|
||||||
ipam: Ipam {
|
ipam: Some(Ipam {
|
||||||
config: Some(vec![ipam_config]),
|
config: Some(vec![ipam_config]),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
match docker.create_network(create_network_options).await {
|
match docker.create_network(create_network_options).await {
|
||||||
Ok(n)=> Ok(Network {
|
Ok(_n) => Ok(Network {
|
||||||
name: name,
|
name: name,
|
||||||
range: range,
|
range: range,
|
||||||
}),
|
}),
|
||||||
Err(e)=> Err(e),
|
Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
mod deploy;
|
|
||||||
mod api;
|
mod api;
|
||||||
mod database;
|
|
||||||
mod controller;
|
mod controller;
|
||||||
|
mod database;
|
||||||
|
mod deploy;
|
||||||
|
|
||||||
#[actix_web::main]
|
#[actix_web::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
api::routes::start().await;
|
_ = api::routes::start().await;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user