use rusqlite::{Connection, Result}; use fallible_iterator::FallibleIterator; pub mod storage; const PATH: &str = "mdeploy.db"; pub struct ConfServer{ ip: String, port: String, ip_top_limit: u8, ip_base_limit: u8, } pub struct Instance { id: i64, pub docker_id: String, pub ip: String, pub domain: String, pub image: i64, } pub struct InstanceStorage { con: Connection, } impl InstanceStorage { pub fn new() -> Result { let con = Connection::open(PATH)?; let ret = Self { con : con, }; ret.create_table()?; Ok(ret) } fn create_table(&self) -> Result<()> { self.con.execute_batch( "BEGIN; CREATE TABLE IF NOT EXISTS images( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE); CREATE TABLE IF NOT EXISTS l_instances( id INTEGER PRIMARY KEY AUTOINCREMENT, docker_id TEXT, ip TEXT, domain TEXT, image INTEGER, FOREIGN KEY(image) REFERENCES images(id)); COMMIT;" ) } fn insert_image(&self, image: String) -> Result<()>{ let mut stmt = self.con.prepare("INSERT INTO images(name) values(?1)")?; stmt.execute([image])?; Ok(()) } fn load_instances(&mut self) -> Result> { let mut stmt = self.con.prepare("select id, docker_id, ip, domain, image from l_instances")?; let mut rows = stmt.query([])?; rows.map(|r| Ok(Instance{ id: r.get::<_, i64>(0)?, docker_id: r.get::<_, String>(1)?, ip: r.get::<_, String>(2)?, domain: r.get::<_, String>(3)?, image: r.get::<_, i64>(4)?, })).collect() } fn load_images(&mut self) -> Result> { let mut stmt = self.con.prepare("select id, name from images")?; let mut rows = stmt.query([])?; rows.map(|row| Ok((row.get::<_, String>(1)?, row.get::<_, i64>(0)?))).collect() } fn get_image_id(&self, image: String) -> Result> { let mut stmt = self.con.prepare("select id from images where name = ?1")?; let mut rows = stmt.query([image])?; Ok(match rows.next()? { Some(i) => Some(i.get::<_, i64>(0)?), None => None, }) } pub fn get_image_name(&self, id: i64) -> Result { let mut stmt = self.con.prepare("select name from images where id = ?1")?; let mut rows = stmt.query([id])?; Ok(rows.next()?.unwrap().get::<_, String>(0)?) } fn get_instance_id(&self, domain: String) -> Result> { let mut stmt = self.con.prepare("select id from l_instances where domain = ?1")?; let mut rows = stmt.query([domain])?; Ok(match rows.next()? { Some(i) => Some(i.get::<_, i64>(0)?), None => None, }) } pub fn new_instance(&mut self, docker_id: String, ip: String, domain: String, image: i64) -> Result{ //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, image) values(?1, ?2, ?3, ?4)")?; stmt.execute([docker_id.clone(), ip.clone(), domain.clone(), image.to_string()])?; Ok(Instance { id: image, docker_id: docker_id, ip: ip, domain: domain, image: image, }) } pub fn image_to_id(&self, image: String) -> Result { self.create_or_get_image_id(image, 0) } fn create_or_get_image_id(&self, image: String, mut depth: i64) -> Result { if depth > 1 { return Err(rusqlite::Error::QueryReturnedNoRows); } depth+=1; match self.get_image_id(image.clone()) { Ok(Some(id)) => Ok(id), Ok(None) => { self.insert_image(image.clone())?; self.create_or_get_image_id(image, depth) } Err(_e) => { self.insert_image(image.clone())?; self.create_or_get_image_id(image, depth) } } } }