use anyhow::Result;
use k8_types::{Crd, Spec};
use k8_types::options::ListOptions;
use crate::http::Uri;
use crate::meta_client::NameSpace;
pub fn item_uri<S>(
host: &str,
name: &str,
namespace: &str,
sub_resource: Option<&str>,
query: Option<&str>,
) -> Result<Uri>
where
S: Spec,
{
let ns = if S::NAME_SPACED {
NameSpace::Named(namespace.to_owned())
} else {
NameSpace::All
};
let crd = S::metadata();
let prefix = prefix_uri(crd, host, ns, None);
let sub_resource = sub_resource.unwrap_or("");
let query = query.map(|q| format!("?{q}")).unwrap_or_default();
let uri_value = format!("{prefix}/{name}{sub_resource}{query}");
let uri: Uri = uri_value.parse()?;
Ok(uri)
}
pub fn items_uri<S>(host: &str, namespace: NameSpace, list_options: Option<ListOptions>) -> Uri
where
S: Spec,
{
let ns = if S::NAME_SPACED {
namespace
} else {
NameSpace::All
};
let crd = S::metadata();
let uri_value = prefix_uri(crd, host, ns, list_options);
let uri: Uri = uri_value.parse().unwrap();
uri
}
pub fn prefix_uri<N>(crd: &Crd, host: &str, ns: N, options: Option<ListOptions>) -> String
where
N: Into<NameSpace>,
{
let namespace = ns.into();
let version = crd.version;
let plural = crd.names.plural;
let group = crd.group;
let api_prefix = match group {
"core" => "api".to_owned(),
_ => format!("apis/{group}"),
};
let query = if let Some(opt) = options {
let mut query = "?".to_owned();
let qs = serde_qs::to_string(&opt).unwrap();
query.push_str(&qs);
query
} else {
"".to_owned()
};
if namespace.is_all() {
format!("{host}/{api_prefix}/{version}/{plural}{query}")
} else {
format!(
"{}/{}/{}/namespaces/{}/{}{}",
host,
api_prefix,
version,
namespace.named(),
plural,
query
)
}
}
#[cfg(test)]
mod test {
use k8_metadata_client::ApplyOptions;
use k8_types::core::pod::PodSpec;
use k8_types::{Crd, CrdNames, DEFAULT_NS};
use super::{prefix_uri, item_uri};
use super::ListOptions;
const G1: Crd = Crd {
group: "test.com",
version: "v1",
names: CrdNames {
kind: "Item",
plural: "items",
singular: "item",
},
};
const C1: Crd = Crd {
group: "core",
version: "v1",
names: CrdNames {
kind: "Item",
plural: "items",
singular: "item",
},
};
#[test]
fn test_api_prefix_group() {
let uri = prefix_uri(&G1, "https://localhost", DEFAULT_NS, None);
assert_eq!(
uri,
"https://localhost/apis/test.com/v1/namespaces/default/items"
);
}
#[test]
fn test_api_prefix_core() {
let uri = prefix_uri(&C1, "https://localhost", DEFAULT_NS, None);
assert_eq!(uri, "https://localhost/api/v1/namespaces/default/items");
}
#[test]
fn test_api_prefix_watch() {
let opt = ListOptions {
watch: Some(true),
..Default::default()
};
let uri = prefix_uri(&C1, "https://localhost", DEFAULT_NS, Some(opt));
assert_eq!(
uri,
"https://localhost/api/v1/namespaces/default/items?watch=true"
);
}
#[test]
fn test_list_query() {
let opt = ListOptions {
pretty: Some(true),
watch: Some(true),
..Default::default()
};
let qs = serde_qs::to_string(&opt).unwrap();
assert_eq!(qs, "pretty=true&watch=true")
}
#[test]
fn support_item_uri_params() {
let patch_params = ApplyOptions {
force: true,
field_manager: Some(String::from("fluvio")),
};
let params = serde_qs::to_string(&patch_params).unwrap();
let uri = item_uri::<PodSpec>(
"http://localhost:8001",
"test",
DEFAULT_NS,
Some("/status"),
Some(¶ms),
);
assert_eq!(
uri.unwrap().to_string(),
"http://localhost:8001/api/v1/namespaces/default/pods/test/status?force=true&fieldManager=fluvio"
);
}
}