use std::{fs, path::PathBuf}; fn repo_root() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")) .parent() .and_then(|p| p.parent()) .expect("api crate should live under repo root") .to_path_buf() } #[test] fn stack_files_parse_as_yaml() { let root = repo_root(); for file in [ root.join("swarm/stacks/control-plane.yml"), root.join("swarm/stacks/control-plane-prod.yml"), root.join("swarm/stacks/observability.yml"), ] { let raw = fs::read_to_string(&file).unwrap(); let _: serde_yaml::Value = serde_yaml::from_str(&raw).unwrap(); } } #[test] fn control_plane_stack_has_required_services() { let root = repo_root(); let raw = fs::read_to_string(root.join("swarm/stacks/control-plane.yml")).unwrap(); let v: serde_yaml::Value = serde_yaml::from_str(&raw).unwrap(); let services = v .get("services") .and_then(|x| x.as_mapping()) .expect("missing services"); for required in ["control-api", "control-ui"] { assert!( services.contains_key(serde_yaml::Value::String(required.to_string())), "missing service {required}" ); } } #[test] fn control_plane_prod_stack_has_control_api_and_external_s3_secrets() { let root = repo_root(); let raw = fs::read_to_string(root.join("swarm/stacks/control-plane-prod.yml")).unwrap(); let v: serde_yaml::Value = serde_yaml::from_str(&raw).unwrap(); let services = v .get("services") .and_then(|x| x.as_mapping()) .expect("missing services"); assert!(services.contains_key(serde_yaml::Value::String("control-api".to_string()))); assert!(services.contains_key(serde_yaml::Value::String("control-ui".to_string()))); assert!( !services.contains_key(serde_yaml::Value::String("minio".to_string())), "prod stack must not bundle MinIO" ); let secrets = v .get("secrets") .and_then(|x| x.as_mapping()) .expect("missing secrets"); for name in ["control_s3_access_key_id", "control_s3_secret_access_key"] { let entry = secrets .get(serde_yaml::Value::String(name.to_string())) .unwrap_or_else(|| panic!("missing secret {name}")); let external = entry .get(serde_yaml::Value::String("external".to_string())) .and_then(|x| x.as_bool()) .unwrap_or(false); assert!(external, "secret {name} must be external: true"); } }