use std::collections::BTreeMap;
use serde_json::{Value, json};
use crate::registry;
use crate::resources::ResourceKind;
pub fn created_resources(ks_doc: &Value) -> BTreeMap<ResourceKind, String> {
let mut out = BTreeMap::new();
walk_created(ks_doc, &mut out);
out
}
fn walk_created(v: &Value, out: &mut BTreeMap<ResourceKind, String>) {
match v {
Value::Object(map) => {
if let Some(Value::Object(created)) = map.get("createdResources") {
for (member, name) in created {
let kind = match member.as_str() {
"datasource" => Some(ResourceKind::DataSource),
"indexer" => Some(ResourceKind::Indexer),
"skillset" => Some(ResourceKind::Skillset),
"index" => Some(ResourceKind::Index),
_ => None, };
if let (Some(kind), Some(name)) = (kind, name.as_str()) {
out.insert(kind, name.to_string());
}
}
}
for val in map.values() {
walk_created(val, out);
}
}
Value::Array(arr) => {
for item in arr {
walk_created(item, out);
}
}
_ => {}
}
}
pub fn is_indexed_with_created(ks_doc: &Value) -> bool {
ks_doc.get("kind").and_then(Value::as_str) != Some("searchIndex")
&& !created_resources(ks_doc).is_empty()
}
pub fn to_search_index_ks(ks_doc: &Value, index_name: &str) -> Value {
let mut out = json!({
"name": ks_doc.get("name").cloned().unwrap_or(Value::Null),
"kind": "searchIndex",
"searchIndexParameters": { "searchIndexName": index_name }
});
if let Some(desc) = ks_doc.get("description").filter(|d| !d.is_null()) {
out["description"] = desc.clone();
}
out
}
pub fn derive_names(
old_ks: &str,
new_ks: &str,
created: &BTreeMap<ResourceKind, String>,
) -> BTreeMap<ResourceKind, String> {
created
.iter()
.map(|(kind, name)| {
let derived = match name.strip_prefix(old_ks) {
Some(rest) => format!("{new_ks}{rest}"),
None => {
let suffix = match kind {
ResourceKind::DataSource => "datasource",
ResourceKind::Index => "index",
ResourceKind::Skillset => "skillset",
ResourceKind::Indexer => "indexer",
other => registry::meta(*other).dir_name,
};
format!("{new_ks}-{suffix}")
}
};
(*kind, derived)
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
fn blob_ks() -> Value {
json!({
"name": "regulatory",
"kind": "azureBlob",
"description": "Legal docs.",
"azureBlobParameters": {
"containerName": "regulatory",
"createdResources": {
"datasource": "regulatory-datasource",
"indexer": "regulatory-indexer",
"skillset": "regulatory-skillset",
"index": "regulatory-index",
"somethingFuture": "ignored-name"
}
}
})
}
#[test]
fn created_resources_reads_nested_map() {
let map = created_resources(&blob_ks());
assert_eq!(map.len(), 4);
assert_eq!(map[&ResourceKind::Index], "regulatory-index");
assert_eq!(map[&ResourceKind::DataSource], "regulatory-datasource");
assert_eq!(map[&ResourceKind::Skillset], "regulatory-skillset");
assert_eq!(map[&ResourceKind::Indexer], "regulatory-indexer");
}
#[test]
fn is_indexed_with_created_true_for_blob_false_otherwise() {
assert!(is_indexed_with_created(&blob_ks()));
let search_index = json!({"name": "ks", "kind": "searchIndex",
"searchIndexParameters": {"searchIndexName": "docs"}});
assert!(!is_indexed_with_created(&search_index));
let web = json!({"name": "ks", "kind": "web", "webParameters": {}});
assert!(!is_indexed_with_created(&web));
}
#[test]
fn to_search_index_ks_preserves_name_and_description() {
let ks = to_search_index_ks(&blob_ks(), "regulatory-index");
assert_eq!(
ks,
json!({
"name": "regulatory",
"kind": "searchIndex",
"description": "Legal docs.",
"searchIndexParameters": {"searchIndexName": "regulatory-index"}
})
);
}
#[test]
fn to_search_index_ks_omits_missing_description() {
let ks = json!({"name": "n", "kind": "azureBlob", "description": null});
let out = to_search_index_ks(&ks, "i");
assert!(out.get("description").is_none());
}
#[test]
fn derive_names_swaps_prefix() {
let created = created_resources(&blob_ks());
let names = derive_names("regulatory", "reg2", &created);
assert_eq!(names[&ResourceKind::Index], "reg2-index");
assert_eq!(names[&ResourceKind::DataSource], "reg2-datasource");
assert_eq!(names[&ResourceKind::Skillset], "reg2-skillset");
assert_eq!(names[&ResourceKind::Indexer], "reg2-indexer");
}
#[test]
fn derive_names_falls_back_to_conventional_suffix() {
let mut created = BTreeMap::new();
created.insert(ResourceKind::Index, "weird-name".to_string());
let names = derive_names("regulatory", "reg2", &created);
assert_eq!(names[&ResourceKind::Index], "reg2-index");
}
}