1
0
Fork 0
mirror of https://codeberg.org/icewind/haze.git synced 2026-06-03 09:04:12 +02:00

allow running sql queries directly from cli

This commit is contained in:
Robin Appelman 2025-04-03 15:14:07 +02:00
commit 37849081be
4 changed files with 170 additions and 54 deletions

View file

@ -31,7 +31,11 @@ pub enum HazeArgs {
command: Vec<String>, command: Vec<String>,
}, },
/// Connect to the database of an instance /// Connect to the database of an instance
Db { filter: Option<String>, root: bool }, Db {
filter: Option<String>,
root: bool,
command: Vec<String>,
},
/// Remove all non-pinned instances /// Remove all non-pinned instances
Clean, Clean,
/// View the logs from an instance or service /// View the logs from an instance or service
@ -178,10 +182,24 @@ impl HazeArgs {
filter, filter,
command: args.map(S::into).collect(), command: args.map(S::into).collect(),
}), }),
HazeCommand::Db => Ok(HazeArgs::Db { HazeCommand::Db => {
filter, let mut args = args.peekable();
root: args.next().filter(|arg| arg.as_ref() == "root").is_some(), let root = if let Some(first) = args.peek() {
}), let root = first.as_ref() == "root";
if root {
let _ = args.next();
}
root
} else {
false
};
let command = args.map(S::into).collect();
Ok(HazeArgs::Db {
filter,
root,
command,
})
}
HazeCommand::Clean => Ok(HazeArgs::Clean), HazeCommand::Clean => Ok(HazeArgs::Clean),
HazeCommand::Logs => { HazeCommand::Logs => {
let mut args = args.peekable(); let mut args = args.peekable();
@ -338,7 +356,36 @@ fn test_arg_parse() {
HazeArgs::parse(&[], vec!["haze", "asdasd", "db"].into_iter()).unwrap(), HazeArgs::parse(&[], vec!["haze", "asdasd", "db"].into_iter()).unwrap(),
HazeArgs::Db { HazeArgs::Db {
filter: Some("asdasd".to_string()), filter: Some("asdasd".to_string()),
root: false root: false,
command: Vec::new()
}
);
assert_eq!(
HazeArgs::parse(&[], vec!["haze", "asdasd", "db", "root"].into_iter()).unwrap(),
HazeArgs::Db {
filter: Some("asdasd".to_string()),
root: true,
command: Vec::new()
}
);
assert_eq!(
HazeArgs::parse(&[], vec!["haze", "asdasd", "db", "select", "1"].into_iter()).unwrap(),
HazeArgs::Db {
filter: Some("asdasd".to_string()),
root: false,
command: vec!["select".to_string(), "1".to_string()]
}
);
assert_eq!(
HazeArgs::parse(
&[],
vec!["haze", "asdasd", "db", "root", "select 1"].into_iter()
)
.unwrap(),
HazeArgs::Db {
filter: Some("asdasd".to_string()),
root: true,
command: vec!["select 1".to_string()]
} }
); );
assert_eq!( assert_eq!(

View file

@ -265,53 +265,118 @@ impl Database {
} }
} }
pub async fn exec(&self, docker: &Docker, cloud_id: &str, root: bool) -> Result<ExitCode> { pub async fn exec(
match self.family() { &self,
DatabaseFamily::Sqlite => { docker: &Docker,
exec_tty( cloud_id: &str,
docker, root: bool,
cloud_id, command: &[String],
"haze", ) -> Result<ExitCode> {
vec!["sqlite3", "/var/www/html/data/haze.db"], let command = command.join(" ");
Vec::<String>::default(), if command.is_empty() {
) match self.family() {
.await DatabaseFamily::Sqlite => {
} exec_tty(
DatabaseFamily::MariaDB | DatabaseFamily::Mysql => { docker,
exec_tty( cloud_id,
docker,
format!("{}-db", cloud_id),
"mysql",
vec![
"mysql",
"-u",
if root { "root" } else { "haze" },
"-phaze",
"haze", "haze",
], vec!["sqlite3", "/var/www/html/data/haze.db"],
Vec::<String>::default(), Vec::<String>::default(),
) )
.await .await
}
DatabaseFamily::MariaDB | DatabaseFamily::Mysql => {
exec_tty(
docker,
format!("{}-db", cloud_id),
"mysql",
vec![
"mysql",
"-u",
if root { "root" } else { "haze" },
"-phaze",
"haze",
],
Vec::<String>::default(),
)
.await
}
DatabaseFamily::Postgres => {
exec_tty(
docker,
format!("{}-db", cloud_id),
"root",
vec!["psql", "haze", "haze"],
vec!["PGPASSWORD=haze"],
)
.await
}
DatabaseFamily::Oracle => {
exec_tty(
docker,
format!("{}-db", cloud_id),
"root",
vec!["sqlplus", "system/haze"],
Vec::<String>::default(),
)
.await
}
} }
DatabaseFamily::Postgres => { } else {
exec_tty( let stdout = stdout();
docker, match self.family() {
format!("{}-db", cloud_id), DatabaseFamily::Sqlite => {
"root", exec(
vec!["psql", "haze", "haze"], docker,
vec!["PGPASSWORD=haze"], cloud_id,
) "haze",
.await vec!["sqlite3", "/var/www/html/data/haze.db", "-cmd", &command],
} Vec::<String>::default(),
DatabaseFamily::Oracle => { Some(stdout),
exec_tty( )
docker, .await
format!("{}-db", cloud_id), }
"root", DatabaseFamily::MariaDB | DatabaseFamily::Mysql => {
vec!["sqlplus", "system/haze"], exec(
Vec::<String>::default(), docker,
) format!("{}-db", cloud_id),
.await "mysql",
vec![
"mysql",
"-u",
if root { "root" } else { "haze" },
"-phaze",
"haze",
"-e",
&command,
],
Vec::<String>::default(),
Some(stdout),
)
.await
}
DatabaseFamily::Postgres => {
exec(
docker,
format!("{}-db", cloud_id),
"root",
vec!["psql", "haze", "haze", "-c", &command],
vec!["PGPASSWORD=haze"],
Some(stdout),
)
.await
}
DatabaseFamily::Oracle => {
exec(
docker,
format!("{}-db", cloud_id),
"root",
vec!["sqlplus", "system/haze"],
Vec::<String>::default(),
Some(stdout),
)
.await
}
} }
} }
} }

View file

@ -160,9 +160,13 @@ async fn main() -> Result<ExitCode> {
) )
.await?; .await?;
} }
HazeArgs::Db { filter, root } => { HazeArgs::Db {
filter,
root,
command,
} => {
let cloud = Cloud::get_by_filter(&docker, filter, &config).await?; let cloud = Cloud::get_by_filter(&docker, filter, &config).await?;
cloud.db().exec(&docker, &cloud.id, root).await?; cloud.db().exec(&docker, &cloud.id, root, &command).await?;
} }
HazeArgs::Open { filter } => { HazeArgs::Open { filter } => {
let cloud = Cloud::get_by_filter(&docker, filter, &config).await?; let cloud = Cloud::get_by_filter(&docker, filter, &config).await?;

View file

@ -226,7 +226,7 @@ async fn handler(State(state): State<AppState>, mut req: Request) -> Result<Resp
) )
.await .await
{ {
Ok(response) => Ok(response.map(|body| Body::new(body))), Ok(response) => Ok(response.map(Body::new)),
Err(error) => { Err(error) => {
error!(%error, "error while proxying request"); error!(%error, "error while proxying request");
Ok(StatusCode::BAD_REQUEST.into_response()) Ok(StatusCode::BAD_REQUEST.into_response())