From 07768a9322140ab14dd5cc1de28118e8f448f19f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20Berthaud-M=C3=BCller?= Date: Sat, 23 Apr 2022 23:30:20 +0200 Subject: [PATCH] add migrate command to cli --- e2e/zones.py | 3 +- src/cli/mod.rs | 11 +++-- src/cli/serve.rs | 59 ------------------------ src/cli/server.rs | 113 ++++++++++++++++++++++++++++++++++++++++++++++ src/cli/user.rs | 1 - src/main.rs | 1 - 6 files changed, 121 insertions(+), 67 deletions(-) delete mode 100644 src/cli/serve.rs create mode 100644 src/cli/server.rs diff --git a/e2e/zones.py b/e2e/zones.py index d4784de..2770ef9 100644 --- a/e2e/zones.py +++ b/e2e/zones.py @@ -9,6 +9,7 @@ from nomilo_client.models import ( RecordTypeTXT, RecordList, UpdateRecordsRequest, + CreateZoneRequest, ) import logging @@ -154,4 +155,4 @@ class TestZones(unittest.TestCase): if type(record) is RecordTypeTXT and record.name == name: found = True - self.assertFalse(found, msg='Delete record found in zone records') \ No newline at end of file + self.assertFalse(found, msg='Delete record found in zone records') diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 7f5835b..654498c 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -1,4 +1,4 @@ -pub mod serve; +pub mod server; pub mod user; use clap::{Parser, Subcommand}; @@ -6,7 +6,7 @@ use figment::Figment; use crate::config::Config; -use serve::ServeCommand; +use server::ServerCommand; use user::UserCommand; #[derive(Parser)] @@ -19,8 +19,9 @@ pub struct NomiloCli { #[derive(Subcommand)] pub enum Command { - /// Lauch web server - Serve(ServeCommand), + /// Manage web server + #[clap(subcommand)] + Server(ServerCommand), /// Manage users #[clap(subcommand)] User(UserCommand) @@ -34,7 +35,7 @@ pub trait NomiloCommand { impl NomiloCommand for NomiloCli { fn run(self, figment: Figment, app_config: Config) { match self.command { - Command::Serve(sub) => sub.run(figment, app_config), + Command::Server(sub) => sub.run(figment, app_config), Command::User(sub) => sub.run(figment, app_config), }; } diff --git a/src/cli/serve.rs b/src/cli/serve.rs deleted file mode 100644 index 833cef5..0000000 --- a/src/cli/serve.rs +++ /dev/null @@ -1,59 +0,0 @@ -use std::process::exit; - -use clap::Parser; -use rocket::{Rocket, Build}; -use rocket::fairing::AdHoc; -use figment::Figment; - -use crate::config::Config; -use crate::routes::users::*; -use crate::routes::zones::*; -use crate::{DbConn}; -use crate::cli::NomiloCommand; - - -#[derive(Parser)] -pub struct ServeCommand; - -async fn run_migrations(rocket: Rocket) -> Rocket { - embed_migrations!("migrations"); - - let conn = match DbConn::get_one(&rocket).await { - Some(c) => c, - None => { - error!("Could not get a database connection"); - exit(1); - } - }; - - if let Err(e) = conn.run(|c| embedded_migrations::run(c)).await { - error!("Error running migrations: {}", e); - exit(1) - } - - rocket - -} - -impl NomiloCommand for ServeCommand { - fn run(self, figment: Figment, app_config: Config) { - rocket::async_main(async move { - let _res = rocket::custom(figment) - .manage(app_config) - .attach(DbConn::fairing()) - .attach(AdHoc::on_ignite("Database migration", run_migrations)) - .mount("/api/v1", routes![ - get_zone_records, - create_zone_records, - update_zone_records, - delete_zone_records, - get_zones, - create_zone, - add_member_to_zone, - create_auth_token, - create_user, - ]) - .launch().await; - }); - } -} diff --git a/src/cli/server.rs b/src/cli/server.rs new file mode 100644 index 0000000..07d048b --- /dev/null +++ b/src/cli/server.rs @@ -0,0 +1,113 @@ +use std::net::IpAddr; +use std::process::exit; + +use clap::{Parser, Subcommand}; +use rocket::{Rocket, Build}; +use rocket::fairing::AdHoc; +use figment::Figment; + +use crate::config::Config; +use crate::routes::users::*; +use crate::routes::zones::*; +use crate::{DbConn, get_db_conn}; +use crate::cli::NomiloCommand; + +#[derive(Subcommand)] +pub enum ServerCommand { + /// Run web server + Run(RunServerCommand), + /// Run database migrations and exit + Migrate(MigrateCommand), +} + +#[derive(Parser)] +pub struct RunServerCommand { + #[clap(long = "--address", short = 'a')] + /// Address to serve application on, override both configuration and environment values + address: Option, + #[clap(long = "--port", short = 'p')] + /// Port to serve application on, override both configuration and environment values + port: Option, +} + +#[derive(Parser)] +pub struct MigrateCommand; + + +impl NomiloCommand for ServerCommand { + fn run(self, figment: Figment, app_config: Config) { + match self { + ServerCommand::Run(sub) => sub.run(figment, app_config), + ServerCommand::Migrate(sub) => sub.run(figment, app_config), + }; + } +} + +fn run_migrations(conn: &diesel::SqliteConnection) -> Result<(), diesel_migrations::RunMigrationsError> { + embed_migrations!("migrations"); + embedded_migrations::run(conn) +} + + +async fn run_migrations_fairing(rocket: Rocket) -> Rocket { + embed_migrations!("migrations"); + + let conn = match DbConn::get_one(&rocket).await { + Some(c) => c, + None => { + error!("Could not get a database connection"); + exit(1); + } + }; + + if let Err(e) = conn.run(|c| run_migrations(&c)).await { + error!("Error running migrations: {}", e); + exit(1); + } + + rocket + +} + +impl NomiloCommand for RunServerCommand { + fn run(self, mut figment: Figment, app_config: Config) { + rocket::async_main(async move { + if let Some(address) = self.address { + figment = figment.merge(("address", address)); + } + if let Some(port) = self.port { + figment = figment.merge(("port", port)); + } + let _res = rocket::custom(figment) + .manage(app_config) + .attach(DbConn::fairing()) + .attach(AdHoc::on_ignite("Database migration", run_migrations_fairing)) + .mount("/api/v1", routes![ + get_zone_records, + create_zone_records, + update_zone_records, + delete_zone_records, + get_zones, + create_zone, + add_member_to_zone, + create_auth_token, + create_user, + ]) + .launch().await; + }); + } +} + +impl NomiloCommand for MigrateCommand { + fn run(self, figment: Figment, _app_config: Config) { + let conn = get_db_conn(&figment); + + match run_migrations(&conn) { + Ok(_) => println!("Migrations ran successfully"), + Err(e) => { + error!("Error running migrations: {}", e); + exit(1); + } + } + } +} diff --git a/src/cli/user.rs b/src/cli/user.rs index 9835487..7eb4f4c 100644 --- a/src/cli/user.rs +++ b/src/cli/user.rs @@ -38,7 +38,6 @@ impl NomiloCommand for UserCommand { impl NomiloCommand for AddUserCommand { fn run(self, figment: Figment, _app_config: Config) { - let res = LocalUser::create_user(&get_db_conn(&figment), CreateUserRequest { username: self.name, email: self.email, diff --git a/src/main.rs b/src/main.rs index 89342c3..d39abbf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,7 +26,6 @@ pub struct DbConn(diesel::SqliteConnection); pub fn get_db_conn(figment: &Figment) -> diesel::SqliteConnection { - let url = match figment.focus("databases.sqlite").extract_inner::("url") { Ok(url) => url, Err(e) => {