mirror of
https://codeberg.org/icewind/haze.git
synced 2026-06-04 01:24:09 +02:00
basic subcommands
This commit is contained in:
parent
d426b537b2
commit
da1e184e42
3 changed files with 192 additions and 41 deletions
45
src/args.rs
45
src/args.rs
|
|
@ -1,12 +1,11 @@
|
|||
use color_eyre::{eyre::WrapErr, Report, Result};
|
||||
use std::env::Args;
|
||||
use color_eyre::{Report, Result};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct HazeArgs {
|
||||
id: Option<String>,
|
||||
command: Command,
|
||||
options: Vec<String>,
|
||||
pub id: Option<String>,
|
||||
pub command: HazeCommand,
|
||||
pub options: Vec<String>,
|
||||
}
|
||||
|
||||
impl HazeArgs {
|
||||
|
|
@ -24,11 +23,11 @@ impl HazeArgs {
|
|||
if let Some(sub) = args.next() {
|
||||
(Some(sub_or_id.to_string()), sub.as_ref().parse()?)
|
||||
} else {
|
||||
(Some(sub_or_id.to_string()), Command::List)
|
||||
(Some(sub_or_id.to_string()), HazeCommand::List)
|
||||
}
|
||||
}
|
||||
}
|
||||
None => (None, Command::List),
|
||||
None => (None, HazeCommand::List),
|
||||
};
|
||||
let options = args.map(|s| s.to_string()).collect();
|
||||
Ok(HazeArgs {
|
||||
|
|
@ -40,7 +39,7 @@ impl HazeArgs {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum Command {
|
||||
pub enum HazeCommand {
|
||||
List,
|
||||
Start,
|
||||
Stop,
|
||||
|
|
@ -48,20 +47,22 @@ pub enum Command {
|
|||
Exec,
|
||||
Occ,
|
||||
Db,
|
||||
Clean,
|
||||
}
|
||||
|
||||
impl FromStr for Command {
|
||||
impl FromStr for HazeCommand {
|
||||
type Err = Report;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"list" => Ok(Command::List),
|
||||
"start" => Ok(Command::Start),
|
||||
"stop" => Ok(Command::Stop),
|
||||
"test" => Ok(Command::Test),
|
||||
"exec" => Ok(Command::Exec),
|
||||
"occ" => Ok(Command::Occ),
|
||||
"db" => Ok(Command::Db),
|
||||
"list" => Ok(HazeCommand::List),
|
||||
"start" => Ok(HazeCommand::Start),
|
||||
"stop" => Ok(HazeCommand::Stop),
|
||||
"test" => Ok(HazeCommand::Test),
|
||||
"exec" => Ok(HazeCommand::Exec),
|
||||
"occ" => Ok(HazeCommand::Occ),
|
||||
"db" => Ok(HazeCommand::Db),
|
||||
"clean" => Ok(HazeCommand::Clean),
|
||||
_ => Err(Report::msg(format!("Unknown command: {}", s))),
|
||||
}
|
||||
}
|
||||
|
|
@ -73,7 +74,7 @@ fn test_arg_parse() {
|
|||
HazeArgs::parse(vec!["haze"].into_iter()).unwrap(),
|
||||
HazeArgs {
|
||||
id: None,
|
||||
command: Command::List,
|
||||
command: HazeCommand::List,
|
||||
options: Vec::new(),
|
||||
}
|
||||
);
|
||||
|
|
@ -81,7 +82,7 @@ fn test_arg_parse() {
|
|||
HazeArgs::parse(vec!["haze", "test"].into_iter()).unwrap(),
|
||||
HazeArgs {
|
||||
id: None,
|
||||
command: Command::Test,
|
||||
command: HazeCommand::Test,
|
||||
options: Vec::new(),
|
||||
}
|
||||
);
|
||||
|
|
@ -89,7 +90,7 @@ fn test_arg_parse() {
|
|||
HazeArgs::parse(vec!["haze", "asdasd"].into_iter()).unwrap(),
|
||||
HazeArgs {
|
||||
id: Some("asdasd".to_string()),
|
||||
command: Command::List,
|
||||
command: HazeCommand::List,
|
||||
options: Vec::new(),
|
||||
}
|
||||
);
|
||||
|
|
@ -97,7 +98,7 @@ fn test_arg_parse() {
|
|||
HazeArgs::parse(vec!["haze", "asdasd", "db"].into_iter()).unwrap(),
|
||||
HazeArgs {
|
||||
id: Some("asdasd".to_string()),
|
||||
command: Command::Db,
|
||||
command: HazeCommand::Db,
|
||||
options: Vec::new(),
|
||||
}
|
||||
);
|
||||
|
|
@ -105,7 +106,7 @@ fn test_arg_parse() {
|
|||
HazeArgs::parse(vec!["haze", "exec", "foo", "bar"].into_iter()).unwrap(),
|
||||
HazeArgs {
|
||||
id: None,
|
||||
command: Command::Exec,
|
||||
command: HazeCommand::Exec,
|
||||
options: vec!["foo".to_string(), "bar".to_string()],
|
||||
}
|
||||
);
|
||||
|
|
@ -113,7 +114,7 @@ fn test_arg_parse() {
|
|||
HazeArgs::parse(vec!["haze", "asdasd", "exec", "foo", "bar"].into_iter()).unwrap(),
|
||||
HazeArgs {
|
||||
id: Some("asdasd".to_string()),
|
||||
command: Command::Exec,
|
||||
command: HazeCommand::Exec,
|
||||
options: vec!["foo".to_string(), "bar".to_string()],
|
||||
}
|
||||
);
|
||||
|
|
|
|||
140
src/cloud.rs
140
src/cloud.rs
|
|
@ -14,7 +14,7 @@ use std::time::Duration;
|
|||
use tokio::fs::{create_dir_all, remove_dir_all, write};
|
||||
use tokio::time::sleep;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
#[allow(dead_code)]
|
||||
pub enum Database {
|
||||
Sqlite,
|
||||
|
|
@ -43,15 +43,30 @@ impl Default for Database {
|
|||
}
|
||||
|
||||
impl FromStr for Database {
|
||||
type Err = ();
|
||||
type Err = Report;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"sqlite" => Ok(Database::Sqlite),
|
||||
"mysql" => Ok(Database::Mysql),
|
||||
"mysql:8" => Ok(Database::Mysql80),
|
||||
"mysql:5" => Ok(Database::Mysql57),
|
||||
"mysql:5.7" => Ok(Database::Mysql57),
|
||||
"mysql:5.6" => Ok(Database::Mysql56),
|
||||
"mariadb" => Ok(Database::MariaDB),
|
||||
"postgresql" => Ok(Database::Postgres),
|
||||
_ => Err(()),
|
||||
"mariadb:10.1" => Ok(Database::MariaDB101),
|
||||
"mariadb:10.2" => Ok(Database::MariaDB102),
|
||||
"mariadb:10.3" => Ok(Database::MariaDB103),
|
||||
"mariadb:10.4" => Ok(Database::MariaDB104),
|
||||
"mariadb:10.5" => Ok(Database::MariaDB105),
|
||||
"mariadb:10" => Ok(Database::MariaDB105),
|
||||
"pgsql" => Ok(Database::Postgres),
|
||||
"pgsql:9" => Ok(Database::Postgres9),
|
||||
"pgsql:10" => Ok(Database::Postgres10),
|
||||
"pgsql:11" => Ok(Database::Postgres11),
|
||||
"pgsql:12" => Ok(Database::Postgres12),
|
||||
"pgsql:13" => Ok(Database::Postgres13),
|
||||
_ => Err(Report::msg("Unknown db type")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -163,7 +178,7 @@ impl Database {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
#[allow(dead_code)]
|
||||
pub enum PhpVersion {
|
||||
Latest,
|
||||
|
|
@ -172,6 +187,18 @@ pub enum PhpVersion {
|
|||
// Php73,
|
||||
}
|
||||
|
||||
impl FromStr for PhpVersion {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"7" => Ok(PhpVersion::Php74),
|
||||
"7.4" => Ok(PhpVersion::Php74),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PhpVersion {
|
||||
fn image(&self) -> &'static str {
|
||||
// for now only 7.4
|
||||
|
|
@ -181,6 +208,13 @@ impl PhpVersion {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &'static str {
|
||||
match self {
|
||||
PhpVersion::Latest => "7.4",
|
||||
PhpVersion::Php74 => "7.4",
|
||||
}
|
||||
}
|
||||
|
||||
async fn spawn(
|
||||
&self,
|
||||
docker: &mut Docker,
|
||||
|
|
@ -206,6 +240,7 @@ impl PhpVersion {
|
|||
labels: Some(hashmap! {
|
||||
"haze-type".to_string() => "cloud".to_string(),
|
||||
"haze-db".to_string() => db.name().to_string(),
|
||||
"haze-php".to_string() => self.name().to_string(),
|
||||
"haze-cloud-id".to_string() => id.to_string(),
|
||||
}),
|
||||
..Default::default()
|
||||
|
|
@ -223,20 +258,97 @@ impl Default for PhpVersion {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
#[derive(Default, Debug, Eq, PartialEq)]
|
||||
pub struct CloudOptions {
|
||||
db: Database,
|
||||
php: PhpVersion,
|
||||
}
|
||||
|
||||
impl CloudOptions {
|
||||
pub fn parse<S>(options: Vec<S>) -> Result<(CloudOptions, Vec<S>)>
|
||||
where
|
||||
S: AsRef<str> + Clone,
|
||||
{
|
||||
let mut db = Database::default();
|
||||
let mut php = PhpVersion::default();
|
||||
let mut used = 0;
|
||||
|
||||
for option in options.iter() {
|
||||
if let Ok(db_option) = Database::from_str(option.as_ref()) {
|
||||
db = db_option;
|
||||
used += 1;
|
||||
continue;
|
||||
}
|
||||
if let Ok(php_option) = PhpVersion::from_str(option.as_ref()) {
|
||||
php = php_option;
|
||||
used += 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let rest = options[used..].to_vec();
|
||||
|
||||
Ok((CloudOptions { db, php }, rest))
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_option_parse() {
|
||||
assert_eq!(
|
||||
CloudOptions::parse::<&str>(vec![]).unwrap(),
|
||||
(CloudOptions::default(), vec![])
|
||||
);
|
||||
assert_eq!(
|
||||
CloudOptions::parse(vec!["mariadb"]).unwrap(),
|
||||
(
|
||||
CloudOptions {
|
||||
db: Database::MariaDB,
|
||||
..Default::default()
|
||||
},
|
||||
vec![]
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
CloudOptions::parse(vec!["rest"]).unwrap(),
|
||||
(
|
||||
CloudOptions {
|
||||
..Default::default()
|
||||
},
|
||||
vec!["rest"]
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
CloudOptions::parse(vec!["7"]).unwrap(),
|
||||
(
|
||||
CloudOptions {
|
||||
php: PhpVersion::Php74,
|
||||
..Default::default()
|
||||
},
|
||||
vec![]
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
CloudOptions::parse(vec!["7", "pgsql", "rest"]).unwrap(),
|
||||
(
|
||||
CloudOptions {
|
||||
php: PhpVersion::Php74,
|
||||
db: Database::Postgres,
|
||||
..Default::default()
|
||||
},
|
||||
vec!["rest"]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Cloud {
|
||||
pub id: String,
|
||||
network: String,
|
||||
containers: Vec<String>,
|
||||
db: Database,
|
||||
pub network: String,
|
||||
pub containers: Vec<String>,
|
||||
pub php: PhpVersion,
|
||||
pub db: Database,
|
||||
pub ip: IpAddr,
|
||||
workdir: Utf8PathBuf,
|
||||
pub workdir: Utf8PathBuf,
|
||||
}
|
||||
|
||||
impl Cloud {
|
||||
|
|
@ -360,6 +472,7 @@ impl Cloud {
|
|||
id,
|
||||
network,
|
||||
containers,
|
||||
php: options.php,
|
||||
db: options.db,
|
||||
ip,
|
||||
workdir,
|
||||
|
|
@ -411,7 +524,7 @@ async fn setup_workdir(base: &Utf8Path, id: &str) -> Result<Utf8PathBuf> {
|
|||
Ok(workdir)
|
||||
}
|
||||
|
||||
pub async fn parse(docker: &mut Docker, config: &HazeConfig) -> Result<Vec<Cloud>> {
|
||||
pub async fn list(docker: &mut Docker, config: &HazeConfig) -> Result<Vec<Cloud>> {
|
||||
let containers = docker.list_containers::<String>(None).await?;
|
||||
let mut containers_by_id: HashMap<String, (Option<_>, Vec<_>)> = HashMap::new();
|
||||
for container in containers {
|
||||
|
|
@ -434,7 +547,9 @@ pub async fn parse(docker: &mut Docker, config: &HazeConfig) -> Result<Vec<Cloud
|
|||
let networks = cloud.network_settings?.networks?;
|
||||
let network_info = networks.get(&network)?;
|
||||
let workdir = config.work_dir.join(&id);
|
||||
let db = cloud.labels?.get("haze-db")?.parse().ok()?;
|
||||
let labels = cloud.labels?;
|
||||
let db = labels.get("haze-db")?.parse().ok()?;
|
||||
let php = labels.get("haze-php")?.parse().ok()?;
|
||||
let mut service_ids: Vec<String> = services
|
||||
.iter()
|
||||
.filter_map(|service| service.names.as_ref()?.first().map(String::clone))
|
||||
|
|
@ -444,6 +559,7 @@ pub async fn parse(docker: &mut Docker, config: &HazeConfig) -> Result<Vec<Cloud
|
|||
id,
|
||||
network,
|
||||
db,
|
||||
php,
|
||||
containers: service_ids,
|
||||
ip: network_info.ip_address.as_ref()?.parse().ok()?,
|
||||
workdir,
|
||||
|
|
|
|||
48
src/main.rs
48
src/main.rs
|
|
@ -1,7 +1,8 @@
|
|||
use crate::cloud::{parse, Cloud, CloudOptions};
|
||||
use crate::args::{HazeArgs, HazeCommand};
|
||||
use crate::cloud::{list, Cloud, CloudOptions};
|
||||
use crate::config::HazeConfig;
|
||||
use bollard::Docker;
|
||||
use color_eyre::{eyre::WrapErr, Result};
|
||||
use color_eyre::{eyre::WrapErr, Report, Result};
|
||||
|
||||
mod args;
|
||||
mod cloud;
|
||||
|
|
@ -15,13 +16,46 @@ async fn main() -> Result<()> {
|
|||
sources_root: "/srv/http/owncloud".into(),
|
||||
work_dir: "/tmp/haze".into(),
|
||||
};
|
||||
let options = CloudOptions::default();
|
||||
|
||||
// let cloud = Cloud::create(&mut docker, options, &config).await?;
|
||||
// println!("{} running on http://{}", cloud.id, cloud.ip);
|
||||
let args = HazeArgs::parse(std::env::args())?;
|
||||
dbg!(&args);
|
||||
|
||||
let clouds = parse(&mut docker, &config).await?;
|
||||
dbg!(clouds);
|
||||
match args.command {
|
||||
HazeCommand::Clean => {
|
||||
let list = list(&mut docker, &config).await?;
|
||||
for cloud in list {
|
||||
if let Err(e) = cloud.destroy(&mut docker).await {
|
||||
eprintln!("Error while removing cloud: {:#}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
HazeCommand::List => {
|
||||
let list = list(&mut docker, &config).await?;
|
||||
for cloud in list {
|
||||
if let Some(filter) = &args.id {
|
||||
if !cloud.id.contains(filter.as_str()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
println!(
|
||||
"Cloud {}, {}, {}, running on http://{}",
|
||||
cloud.id,
|
||||
cloud.php.name(),
|
||||
cloud.db.name(),
|
||||
cloud.ip
|
||||
)
|
||||
}
|
||||
}
|
||||
HazeCommand::Start => {
|
||||
let (options, rest) = CloudOptions::parse(args.options)?;
|
||||
if let Some(next) = rest.first() {
|
||||
return Err(Report::msg(format!("Unknown option {}", next)));
|
||||
}
|
||||
let cloud = Cloud::create(&mut docker, options, &config).await?;
|
||||
println!("http://{}", cloud.ip);
|
||||
}
|
||||
_ => todo!(),
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue