Files
cli/src/kube.rs

108 lines
3.2 KiB
Rust
Raw Normal View History

use anyhow::{bail, Result};
use std::sync::OnceLock;
static CONTEXT: OnceLock<String> = OnceLock::new();
static SSH_HOST: OnceLock<String> = OnceLock::new();
/// Set the active kubectl context and optional SSH host for production tunnel.
pub fn set_context(ctx: &str, ssh_host: &str) {
let _ = CONTEXT.set(ctx.to_string());
let _ = SSH_HOST.set(ssh_host.to_string());
}
/// Get the active context.
pub fn context() -> &'static str {
CONTEXT.get().map(|s| s.as_str()).unwrap_or("sunbeam")
}
/// Get the SSH host (empty for local).
pub fn ssh_host() -> &'static str {
SSH_HOST.get().map(|s| s.as_str()).unwrap_or("")
}
/// Parse 'ns/name' -> (Some(ns), Some(name)), 'ns' -> (Some(ns), None), None -> (None, None).
pub fn parse_target(s: Option<&str>) -> Result<(Option<&str>, Option<&str>)> {
match s {
None => Ok((None, None)),
Some(s) => {
let parts: Vec<&str> = s.splitn(3, '/').collect();
match parts.len() {
1 => Ok((Some(parts[0]), None)),
2 => Ok((Some(parts[0]), Some(parts[1]))),
_ => bail!("Invalid target {s:?}: expected 'namespace' or 'namespace/name'"),
}
}
}
}
/// Replace all occurrences of DOMAIN_SUFFIX with domain.
pub fn domain_replace(text: &str, domain: &str) -> String {
text.replace("DOMAIN_SUFFIX", domain)
}
/// Transparent kubectl passthrough for the active context.
pub async fn cmd_k8s(_kubectl_args: &[String]) -> Result<()> {
todo!("cmd_k8s: kubectl passthrough via kube-rs")
}
/// Run bao CLI inside the OpenBao pod with the root token.
pub async fn cmd_bao(_bao_args: &[String]) -> Result<()> {
todo!("cmd_bao: bao passthrough via kube-rs exec")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_target_none() {
let (ns, name) = parse_target(None).unwrap();
assert!(ns.is_none());
assert!(name.is_none());
}
#[test]
fn test_parse_target_namespace_only() {
let (ns, name) = parse_target(Some("ory")).unwrap();
assert_eq!(ns, Some("ory"));
assert!(name.is_none());
}
#[test]
fn test_parse_target_namespace_and_name() {
let (ns, name) = parse_target(Some("ory/kratos")).unwrap();
assert_eq!(ns, Some("ory"));
assert_eq!(name, Some("kratos"));
}
#[test]
fn test_parse_target_too_many_parts() {
assert!(parse_target(Some("too/many/parts")).is_err());
}
#[test]
fn test_parse_target_empty_string() {
let (ns, name) = parse_target(Some("")).unwrap();
assert_eq!(ns, Some(""));
assert!(name.is_none());
}
#[test]
fn test_domain_replace_single() {
let result = domain_replace("src.DOMAIN_SUFFIX/foo", "192.168.1.1.sslip.io");
assert_eq!(result, "src.192.168.1.1.sslip.io/foo");
}
#[test]
fn test_domain_replace_multiple() {
let result = domain_replace("DOMAIN_SUFFIX and DOMAIN_SUFFIX", "x.sslip.io");
assert_eq!(result, "x.sslip.io and x.sslip.io");
}
#[test]
fn test_domain_replace_none() {
let result = domain_replace("no match here", "x.sslip.io");
assert_eq!(result, "no match here");
}
}