use super::topology::Topology;
use crate::aether_tunnel::WireTls;
pub const WIRE_REPLICA_PRESET: &str = "nautalid-wire-client";
pub const HOST_DATA_PRESET: &str = "nautalid-data";
pub fn wire_client_kdl(topology: &Topology, replicate_hex: &str) -> String {
format!(
r#"preset "{WIRE_REPLICA_PRESET}" {{
consistency "strong"
replication {}
shards {}
indexes primary="bplus"
query "{}"
durability "wal"
transport local
route "storage" handler="storage"
route "replicate" handler="replication"
replicate_auth {{
master_key_hex "{replicate_hex}"
}}
}}
"#,
topology.replication, topology.shards, topology.query,
)
}
pub fn wire_client_kdl_tls(
topology: &Topology,
endpoint: &str,
tls: &WireTls,
replicate_hex: &str,
) -> String {
format!(
r#"preset "{WIRE_REPLICA_PRESET}" {{
consistency "strong"
replication {}
shards {}
indexes primary="bplus"
query "{}"
durability "wal"
transport zeromq connect="{endpoint}" pattern="router-dealer" {{
tls {{
cert_file "{}"
key_file "{}"
ca_file "{}"
client_auth #true
}}
}}
route "storage" handler="storage"
route "replicate" handler="replication"
replicate_auth {{
master_key_hex "{replicate_hex}"
}}
}}
"#,
topology.replication,
topology.shards,
topology.query,
tls.cert_file.display(),
tls.key_file.display(),
tls.ca_file.display(),
)
}
pub fn host_data_kdl(
topology: &Topology,
bind: &str,
replicate_hex: &str,
tls_block: &str,
control_key_hex: Option<&str>,
) -> String {
let cluster_block = if topology.is_cluster() {
let leader = if topology.bootstrap_leader() {
"\n bootstrap_leader #true"
} else {
""
};
let control_kwt = control_key_hex.map_or(String::new(), |hex| {
format!(
r#"
kwt {{
mode "required"
audience "nautalid.cluster"
master_key_hex "{hex}"
scope "admin:all"
}}"#
)
});
format!(
r#"
cluster {{
node_id {}
shards {}{leader}{control_kwt}
}}"#,
topology.node_id, topology.shards
)
} else {
String::new()
};
format!(
r#"preset "{HOST_DATA_PRESET}" {{
consistency "strong"
replication {}
shards {}
indexes primary="bplus" secondary="bplus"
query "{}"
durability "wal"
transport zeromq bind="{bind}" pattern="router-dealer"{tls_block}
route "storage" handler="storage"
route "replicate" handler="replication"
route "control" handler="control"
replicate_auth {{
master_key_hex "{replicate_hex}"
}}{cluster_block}
}}
"#,
topology.replication, topology.shards, topology.query,
)
}
pub fn tls_block_from_paths(
cert: &std::path::Path,
key: &std::path::Path,
ca: &std::path::Path,
) -> String {
format!(
r#" {{
tls {{
cert_file "{}"
key_file "{}"
ca_file "{}"
client_auth #true
}}
}}"#,
cert.display(),
key.display(),
ca.display(),
)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::kwt_replay::topology::{DeployMode, Topology};
#[test]
fn cluster_host_kdl_includes_cluster_block() {
let topo = Topology {
mode: DeployMode::Cluster,
shards: 8,
replication: 3,
node_id: 1,
query: "sql".into(),
};
let kdl = host_data_kdl(&topo, "tcp://0.0.0.0:5555", &"aa".repeat(64), "", None);
assert!(kdl.contains("cluster {"));
assert!(kdl.contains("shards 8"));
assert!(kdl.contains(r#"route "control""#));
}
#[test]
fn wire_client_matches_topology_shards() {
let topo = Topology {
mode: DeployMode::Cluster,
shards: 16,
replication: 3,
node_id: 0,
query: "kv".into(),
};
let kdl = wire_client_kdl(&topo, "bb".repeat(64).as_str());
assert!(kdl.contains("shards 16"));
}
}