use super::Command;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SchemaPlan {
Migrate,
Require,
}
#[must_use]
pub fn plan_schema(command: Option<&Command>) -> SchemaPlan {
match command {
None => SchemaPlan::Migrate,
Some(Command::Serve { role }) => {
match role
.unwrap_or_default()
.has(acme_proxy_server::ProcessRole::Worker)
{
true => SchemaPlan::Migrate,
false => SchemaPlan::Require,
}
}
Some(Command::Migrate | Command::Init) => SchemaPlan::Migrate,
_ => SchemaPlan::Require,
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::cli::Cli;
use clap::Parser;
fn plan(argv: &[&str]) -> SchemaPlan {
let cli = Cli::try_parse_from(argv).expect("the command line must parse");
plan_schema(cli.command.as_ref())
}
#[test]
fn a_default_serve_owns_the_schema() {
assert_eq!(plan(&["acme-proxy"]), SchemaPlan::Migrate);
assert_eq!(plan(&["acme-proxy", "serve"]), SchemaPlan::Migrate);
}
#[test]
fn serve_owns_the_schema_exactly_when_it_runs_the_worker() {
for roles in ["worker", "acme,worker", "admin,worker", "acme,admin,worker"] {
assert_eq!(
plan(&["acme-proxy", "serve", "--role", roles]),
SchemaPlan::Migrate,
"`--role {roles}` runs the worker, which owns the schema"
);
}
for roles in ["acme", "admin", "acme,admin"] {
assert_eq!(
plan(&["acme-proxy", "serve", "--role", roles]),
SchemaPlan::Require,
"`--role {roles}` runs no worker and must not migrate"
);
}
}
#[test]
fn migrate_and_init_own_the_schema() {
assert_eq!(plan(&["acme-proxy", "migrate"]), SchemaPlan::Migrate);
assert_eq!(plan(&["acme-proxy", "init"]), SchemaPlan::Migrate);
}
#[test]
fn every_other_command_requires_a_current_schema() {
for argv in [
vec!["acme-proxy", "account", "list"],
vec!["acme-proxy", "order", "list"],
vec!["acme-proxy", "audit", "list"],
vec!["acme-proxy", "jobs", "list"],
vec!["acme-proxy", "eab", "list"],
vec!["acme-proxy", "profile", "list"],
vec!["acme-proxy", "admin", "user", "list"],
vec!["acme-proxy", "transfer", "--to", "postgres://h/db"],
] {
assert_eq!(
plan(&argv),
SchemaPlan::Require,
"`{}` must not migrate",
argv.join(" ")
);
}
}
#[test]
fn an_unknown_role_is_refused_before_anything_is_planned() {
let Err(error) = Cli::try_parse_from(["acme-proxy", "serve", "--role", "wroker"]) else {
panic!("an unknown role must not parse");
};
assert!(error.to_string().contains("wroker"), "{error}");
}
}