validate -> check

This commit is contained in:
naskya 2024-07-01 14:16:03 +09:00
parent dd67433cf1
commit 830ffd9563
Signed by: naskya
GPG key ID: 712D413B3A9FED5C
3 changed files with 30 additions and 34 deletions

View file

@ -85,12 +85,12 @@ You can also specify the revision to update to, but this feature is for developm
fishctl config update v1 fishctl config update v1
``` ```
### Validate the config files ### Check the config files
Execute the following command to validate the config files. Execute the following command to check if the config files are valid:
```sh ```sh
fishctl config validate fishctl config check
``` ```
Please note that some items are only formally checked. Even if the output says it is valid, your settings can be incorrect. Please note that some items are only formally checked. Even if the output says it is valid, your settings can be incorrect.
@ -98,7 +98,7 @@ Please note that some items are only formally checked. Even if the output says i
This command performs a connection check against the PostgreSQL server and the cache server (Valkey/Redis). You can bypass this check using the `--offline` option: This command performs a connection check against the PostgreSQL server and the cache server (Valkey/Redis). You can bypass this check using the `--offline` option:
```sh ```sh
fishctl config validate --offline fishctl config check --offline
``` ```
### Generate VAPID keys for push notifications ### Generate VAPID keys for push notifications

View file

@ -1,7 +1,7 @@
//! `config` subcommand //! `config` subcommand
mod check;
mod update; mod update;
mod validate;
use crate::config::{Revision, CLIENT_CONFIG_PATH, SERVER_CONFIG_PATH}; use crate::config::{Revision, CLIENT_CONFIG_PATH, SERVER_CONFIG_PATH};
use clap::Subcommand; use clap::Subcommand;
@ -14,15 +14,14 @@ use std::{
#[derive(Subcommand)] #[derive(Subcommand)]
pub(crate) enum Commands { pub(crate) enum Commands {
/// Convert old config files to the new format /// Check the config files
Update { revision: Option<Revision> }, Check {
/// Validate the config files
Validate {
#[arg(short, long)] #[arg(short, long)]
/// Do not perform connection checks against database and cache servers /// Do not perform connection checks against database and cache servers
offline: bool, offline: bool,
}, },
/// Update the config files to the latest revision (as of this fishctl release)
Update { revision: Option<Revision> },
} }
/// Errors that can happen in `config` subcommand /// Errors that can happen in `config` subcommand
@ -31,13 +30,13 @@ pub(crate) enum ConfigError {
#[error(transparent)] #[error(transparent)]
Update(#[from] update::UpdateError), Update(#[from] update::UpdateError),
#[error(transparent)] #[error(transparent)]
Validate(#[from] validate::ValidationError), Check(#[from] check::CheckError),
} }
pub(super) async fn run(command: Commands, base_dir: &Path) -> Result<(), ConfigError> { pub(super) async fn run(command: Commands, base_dir: &Path) -> Result<(), ConfigError> {
match command { match command {
Commands::Update { revision } => update::run(revision, base_dir).await?, Commands::Update { revision } => update::run(revision, base_dir).await?,
Commands::Validate { offline } => validate::run(offline, base_dir).await?, Commands::Check { offline } => check::run(offline, base_dir).await?,
} }
Ok(()) Ok(())
} }

View file

@ -1,4 +1,4 @@
//! `config validate` subcommand //! `config check` subcommand
use super::*; use super::*;
use crate::config::{client, server, CLIENT_CONFIG_PATH, SERVER_CONFIG_PATH}; use crate::config::{client, server, CLIENT_CONFIG_PATH, SERVER_CONFIG_PATH};
@ -8,9 +8,9 @@ use sqlx::{postgres::PgConnectOptions, query, ConnectOptions};
use std::path::Path; use std::path::Path;
use validator::Validate; use validator::Validate;
/// Errors that can happen in `config validate` subcommand /// Errors that can happen in `config check` subcommand
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
pub(crate) enum ValidationError { pub(crate) enum CheckError {
#[error(transparent)] #[error(transparent)]
ReadFile(#[from] std::io::Error), ReadFile(#[from] std::io::Error),
#[error(transparent)] #[error(transparent)]
@ -27,35 +27,32 @@ pub(crate) enum ValidationError {
CacheServer, CacheServer,
} }
pub(super) async fn run( pub(super) async fn run(bypass_connection_checks: bool, base_dir: &Path) -> Result<(), CheckError> {
bypass_connection_checks: bool,
base_dir: &Path,
) -> Result<(), ValidationError> {
if current_revision(base_dir)?.next().is_some() { if current_revision(base_dir)?.next().is_some() {
cprintln!("Please first run `<bold>fishctl config update</>` to update your config files."); cprintln!("Please first run `<bold>fishctl config update</>` to update your config files.");
return Err(ValidationError::OutOfDate); return Err(CheckError::OutOfDate);
} }
let server_validation_result = match read_server_config_as::<server::Config>(base_dir) { let server_check_result = match read_server_config_as::<server::Config>(base_dir) {
Ok(config) => config.validate().map_err(|err| { Ok(config) => config.validate().map_err(|err| {
cprintln!("<r!><bold>config/server.toml is invalid.</></>\n{}", err); cprintln!("<r!><bold>config/server.toml is invalid.</></>\n{}", err);
ValidationError::InvalidConfig CheckError::InvalidConfig
}), }),
Err(ReadError::InvalidFormat(err)) => { Err(ReadError::InvalidFormat(err)) => {
cprintln!("<r!><bold>config/server.toml is invalid.</></>\n{}", err); cprintln!("<r!><bold>config/server.toml is invalid.</></>\n{}", err);
Err(ValidationError::InvalidConfig) Err(CheckError::InvalidConfig)
} }
Err(ReadError::ReadFile(err)) => Err(ValidationError::ReadFile(err)), Err(ReadError::ReadFile(err)) => Err(CheckError::ReadFile(err)),
}; };
let client_validation_result = match read_client_config_as::<client::Config>(base_dir) { let client_check_result = match read_client_config_as::<client::Config>(base_dir) {
Ok(config) => config.validate().map_err(|err| { Ok(config) => config.validate().map_err(|err| {
cprintln!( cprintln!(
"<r!><bold>{} is invalid.</></>\n{}", "<r!><bold>{} is invalid.</></>\n{}",
CLIENT_CONFIG_PATH, CLIENT_CONFIG_PATH,
err err
); );
ValidationError::InvalidConfig CheckError::InvalidConfig
}), }),
Err(ReadError::InvalidFormat(err)) => { Err(ReadError::InvalidFormat(err)) => {
cprintln!( cprintln!(
@ -63,21 +60,21 @@ pub(super) async fn run(
CLIENT_CONFIG_PATH, CLIENT_CONFIG_PATH,
err err
); );
Err(ValidationError::InvalidConfig) Err(CheckError::InvalidConfig)
} }
Err(ReadError::ReadFile(err)) => Err(ValidationError::ReadFile(err)), Err(ReadError::ReadFile(err)) => Err(CheckError::ReadFile(err)),
}; };
if server_validation_result.is_ok() && client_validation_result.is_ok() { if server_check_result.is_ok() && client_check_result.is_ok() {
cprintln!( cprintln!(
"<g!><bold>{} and {} are valid!</></>", "<g!><bold>{} and {} are valid!</></>",
SERVER_CONFIG_PATH, SERVER_CONFIG_PATH,
CLIENT_CONFIG_PATH CLIENT_CONFIG_PATH
); );
cprintln!("<bold>Note:</> This command only checks the format of the config files, and its result does not guarantee the correctness of the value."); cprintln!("<bold>Note:</> Some items are only checked formally. This result does not guarantee the correctness of your settings.");
} }
if let Err(err) = server_validation_result.and(client_validation_result) { if let Err(err) = server_check_result.and(client_check_result) {
return Err(err); return Err(err);
} }
@ -92,7 +89,7 @@ pub(super) async fn run(
} }
} }
async fn check_database_connection(db: server::Database) -> Result<(), ValidationError> { async fn check_database_connection(db: server::Database) -> Result<(), CheckError> {
let mut conn = PgConnectOptions::new() let mut conn = PgConnectOptions::new()
.host(&db.host) .host(&db.host)
.port(db.port) .port(db.port)
@ -109,7 +106,7 @@ async fn check_database_connection(db: server::Database) -> Result<(), Validatio
async fn check_cache_server_connection( async fn check_cache_server_connection(
cache_server: server::CacheServer, cache_server: server::CacheServer,
) -> Result<(), ValidationError> { ) -> Result<(), CheckError> {
let url = { let url = {
let mut params = vec!["redis://".to_owned()]; let mut params = vec!["redis://".to_owned()];
@ -133,6 +130,6 @@ async fn check_cache_server_connection(
match pong.as_str() { match pong.as_str() {
"PONG" => Ok(()), "PONG" => Ok(()),
_ => Err(ValidationError::CacheServer), _ => Err(CheckError::CacheServer),
} }
} }