pub const DESTINATION_ALL: &str = "all";
pub fn normalize_destination(raw: &str) -> String {
let s = raw.trim().to_ascii_lowercase();
match s.as_str() {
"all" | "*" | "both" => DESTINATION_ALL.into(),
"cf" | "cloudflare" | "cloudflare-containers" | "cloudflare-container"
| "cloudflare-worker" | "worker" | "workers" => "cloudflare".into(),
"k8s" | "kubernetes" | "kube" => "kubernetes".into(),
"k8s-operator" | "kubernetes-operator" | "operator" => "kubernetes-operator".into(),
"railway" | "rw" => "railway".into(),
"oci" | "registry" | "ghcr" => "oci".into(),
"docker-compose" | "compose" => "docker-compose".into(),
"local" | "preflight" | "test" => "local".into(),
"pm2" => "pm2".into(),
"systemd" => "systemd".into(),
other => other.to_string(),
}
}
pub fn is_all_destinations(destinations: &[String]) -> bool {
destinations
.iter()
.any(|d| normalize_destination(d) == DESTINATION_ALL)
}
pub fn destination_to_provider(destination: &str) -> String {
match normalize_destination(destination).as_str() {
"cloudflare" => "cloudflare-containers".into(),
"kubernetes" => "kubernetes".into(),
"kubernetes-operator" => "kubernetes-operator".into(),
"railway" => "railway".into(),
"oci" => "oci".into(),
"docker-compose" => "docker-compose".into(),
"local" => "local".into(),
"pm2" => "pm2".into(),
"systemd" => "systemd".into(),
other => other.to_string(),
}
}
pub fn provider_to_destination(provider: &str) -> String {
normalize_destination(provider)
}
pub fn is_kubernetes_provider(provider: &str) -> bool {
matches!(
normalize_destination(provider).as_str(),
"kubernetes" | "kubernetes-operator"
)
}
pub fn is_cloudflare_provider(provider: &str) -> bool {
normalize_destination(provider) == "cloudflare"
}
pub fn is_local_provider(provider: &str) -> bool {
normalize_destination(provider) == "local"
}
pub fn is_railway_provider(provider: &str) -> bool {
normalize_destination(provider) == "railway"
}
pub fn is_oci_provider(provider: &str) -> bool {
normalize_destination(provider) == "oci"
}
pub fn provider_priority(provider: &str) -> u8 {
match normalize_destination(provider).as_str() {
"kubernetes-operator" => 0,
"kubernetes" => 1,
"local" => 2,
"cloudflare" => 3,
"oci" | "docker-compose" => 4,
"railway" => 5,
"pm2" | "systemd" => 6,
_ => 9,
}
}
pub fn known_destinations() -> &'static [&'static str] {
&[
"all",
"cloudflare",
"kubernetes",
"kubernetes-operator",
"railway",
"oci",
"docker-compose",
"local",
"pm2",
"systemd",
]
}
pub fn parse_destinations(raw: &[String]) -> Result<Vec<String>, String> {
let mut out = Vec::new();
for item in raw {
for part in item.split(',') {
let part = part.trim();
if part.is_empty() {
continue;
}
let dest = normalize_destination(part);
if dest == DESTINATION_ALL {
return Ok(vec![DESTINATION_ALL.into()]);
}
if !out.iter().any(|d| d == &dest) {
out.push(dest);
}
}
}
if out.is_empty() {
return Err(
"no deploy destinations given (examples: --to all, --to cloudflare,kubernetes, --to kubernetes)"
.into(),
);
}
Ok(out)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn k8s_classification_unchanged() {
assert!(is_kubernetes_provider("kubernetes"));
assert!(is_kubernetes_provider("kubernetes-operator"));
assert!(is_kubernetes_provider("k8s"));
assert!(!is_kubernetes_provider("worker"));
assert!(!is_kubernetes_provider("cloudflare-containers"));
}
#[test]
fn cloudflare_aliases() {
assert!(is_cloudflare_provider("cloudflare-containers"));
assert!(is_cloudflare_provider("cf"));
assert!(is_cloudflare_provider("worker"));
assert_eq!(normalize_destination("CF"), "cloudflare");
assert_eq!(destination_to_provider("cloudflare"), "cloudflare-containers");
assert!(!is_cloudflare_provider("kubernetes"));
}
#[test]
fn operator_still_before_runtime_and_cf() {
assert!(provider_priority("kubernetes-operator") < provider_priority("kubernetes"));
assert!(provider_priority("kubernetes") < provider_priority("cloudflare-containers"));
assert!(provider_priority("kubernetes") < provider_priority("worker"));
assert!(provider_priority("cloudflare") < provider_priority("railway"));
}
#[test]
fn parse_to_list() {
let d = parse_destinations(&[
"cloudflare".into(),
"k8s,railway".into(),
])
.unwrap();
assert_eq!(d, vec!["cloudflare", "kubernetes", "railway"]);
}
#[test]
fn parse_to_all() {
assert_eq!(
parse_destinations(&["all".into()]).unwrap(),
vec!["all"]
);
assert_eq!(
parse_destinations(&["both".into()]).unwrap(),
vec!["all"]
);
assert_eq!(
parse_destinations(&["k8s".into(), "all".into()]).unwrap(),
vec!["all"]
);
assert!(is_all_destinations(&["all".into()]));
assert!(!is_all_destinations(&["kubernetes".into()]));
}
}