use std::path::PathBuf;
use crate::selector::{ProjectMismatch, Target, resolve_target};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum StopPlan {
Everything {
config: PathBuf,
},
Project {
project: String,
},
Service {
service: String,
project: Option<String>,
},
Supervisor,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SupervisorSelectorConflict;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum StopPlanError {
Mismatch(ProjectMismatch),
SupervisorWithSelector,
}
pub fn resolve_plan(
config: PathBuf,
service: Option<&str>,
project: Option<&str>,
supervisor: bool,
) -> Result<StopPlan, StopPlanError> {
if supervisor {
if service.is_some() || project.is_some() {
return Err(StopPlanError::SupervisorWithSelector);
}
return Ok(StopPlan::Supervisor);
}
match resolve_target(service, project).map_err(StopPlanError::Mismatch)? {
Target::Everything => Ok(StopPlan::Everything { config }),
Target::Project { project } => Ok(StopPlan::Project { project }),
Target::Service { service, project } => {
Ok(StopPlan::Service { service, project })
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn cfg() -> PathBuf {
PathBuf::from("/x/systemg.yaml")
}
#[test]
fn no_selectors_stops_everything() {
assert_eq!(
resolve_plan(cfg(), None, None, false).unwrap(),
StopPlan::Everything { config: cfg() }
);
}
#[test]
fn supervisor_flag_targets_the_supervisor() {
assert_eq!(
resolve_plan(cfg(), None, None, true).unwrap(),
StopPlan::Supervisor
);
}
#[test]
fn supervisor_with_a_selector_is_a_conflict() {
assert_eq!(
resolve_plan(cfg(), Some("web"), None, true).unwrap_err(),
StopPlanError::SupervisorWithSelector
);
assert_eq!(
resolve_plan(cfg(), None, Some("alpha"), true).unwrap_err(),
StopPlanError::SupervisorWithSelector
);
}
#[test]
fn project_flag_stops_one_project() {
assert_eq!(
resolve_plan(cfg(), None, Some("alpha"), false).unwrap(),
StopPlan::Project {
project: "alpha".into()
}
);
}
#[test]
fn bare_service_leaves_project_for_resident_resolution() {
assert_eq!(
resolve_plan(cfg(), Some("worker"), None, false).unwrap(),
StopPlan::Service {
service: "worker".into(),
project: None
}
);
}
#[test]
fn qualified_selector_splits_project_and_service() {
assert_eq!(
resolve_plan(cfg(), Some("alpha/worker"), None, false).unwrap(),
StopPlan::Service {
service: "worker".into(),
project: Some("alpha".into())
}
);
}
#[test]
fn project_flag_conflicting_with_selector_is_a_mismatch() {
let err =
resolve_plan(cfg(), Some("beta/worker"), Some("alpha"), false).unwrap_err();
assert_eq!(
err,
StopPlanError::Mismatch(ProjectMismatch {
flag: "alpha".into(),
selector: "beta".into()
})
);
}
}