use std::process::ExitCode;
use ytsaurus_client::{Client, ClientError};
use ytsaurus_yson::YsonNode;
fn main() -> ExitCode {
match run() {
Ok(()) => ExitCode::SUCCESS,
Err(e) => {
eprintln!("\ncluster_info failed: {e}");
ExitCode::FAILURE
}
}
}
fn run() -> Result<(), ClientError> {
let client = Client::from_env()?;
step("Asking the root node when the cluster was created");
let root: NodeInfo = client.get_as("//@")?;
println!(" cluster was created at {}", root.creation_time);
check(
"the creation time came back as a timestamp",
!root.creation_time.is_empty()
&& root.creation_time.contains('T')
&& root.creation_time.ends_with('Z'),
)?;
done(&format!("in account {}", root.account));
step("What the struct did not ask for");
let all = client.get("//@")?;
let offered = match &all.node {
YsonNode::Map(attributes) => attributes.len(),
_ => 0,
};
check(
&format!("the cluster offered {offered} attributes, and the struct named 3"),
offered > 3,
)?;
let asked_directly = client.get("//@type")?;
check(
&format!("//@ is a {} whichever way it is read", root.node_type),
asked_directly.as_str() == Some(root.node_type.as_str()),
)?;
step("The same struct, a different path");
let tmp: NodeInfo = client.get_as("//tmp/@")?;
check(
&format!(
"//tmp is a {} created at {}, in account {}",
tmp.node_type, tmp.creation_time, tmp.account
),
tmp.node_type == "map_node" && !tmp.account.is_empty(),
)?;
step("And one attribute on its own, which is no struct at all");
if client.exists("//sys/@cluster_name")? {
let name: String = client.get_as("//sys/@cluster_name")?;
check(
&format!("this cluster calls itself {name:?}"),
!name.is_empty(),
)?;
} else {
done("//sys/@cluster_name is not set here, which is allowed");
}
step("Asking for a type the answer cannot fit");
match client.get_as::<Impossible>("//@") {
Ok(_) => {
return Err(ClientError::Config(
"a timestamp string was accepted as a number, so the decoder is not checking"
.to_owned(),
));
}
Err(e) => {
check(
"a type that does not fit is an error, not a panic",
matches!(e, ClientError::Decode { .. }),
)?;
println!(" {e}");
}
}
println!("\nOne connection and one typed read, which is the whole Go example.");
println!("Nothing was written: the one example that leaves the cluster as it found it.");
Ok(())
}
#[derive(serde::Deserialize)]
struct NodeInfo {
#[serde(rename = "type")]
node_type: String,
creation_time: String,
account: String,
}
#[derive(serde::Deserialize)]
#[allow(dead_code)]
struct Impossible {
creation_time: u64,
}
fn step(what: &str) {
println!("\n== {what}");
}
fn done(what: &str) {
println!(" ok {what}");
}
fn check(what: &str, passed: bool) -> Result<(), ClientError> {
if passed {
done(what);
return Ok(());
}
eprintln!(" FAIL {what}");
Err(ClientError::Config(format!("check failed: {what}")))
}