add migrate command to cli

main
Hannaeko 2022-04-23 23:30:20 +02:00
parent c32c02a5ac
commit 07768a9322
6 changed files with 121 additions and 67 deletions

View File

@ -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')
self.assertFalse(found, msg='Delete record found in zone records')

View File

@ -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),
};
}

View File

@ -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<Build>) -> Rocket<Build> {
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;
});
}
}

113
src/cli/server.rs 100644
View File

@ -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<IpAddr>,
#[clap(long = "--port", short = 'p')]
/// Port to serve application on, override both configuration and environment values
port: Option<u16>,
}
#[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<Build>) -> Rocket<Build> {
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);
}
}
}
}

View File

@ -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,

View File

@ -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::<String>("url") {
Ok(url) => url,
Err(e) => {