182 lines
5.7 KiB
Rust
182 lines
5.7 KiB
Rust
use super::client::KubeClient;
|
|
use super::types::{NodeCondition, NodeDetails, NodeResources, NodeStatus};
|
|
use k8s_openapi::api::core::v1::{Node, Pod};
|
|
use kube::{api::ListParams, Api};
|
|
|
|
impl KubeClient {
|
|
/// Gets list of all nodes and their statuses
|
|
pub async fn get_nodes(&self) -> Result<Vec<NodeStatus>, Box<dyn std::error::Error>> {
|
|
let nodes: Api<Node> = Api::all(self.inner().clone());
|
|
let node_list = nodes.list(&ListParams::default()).await?;
|
|
|
|
let mut result = Vec::new();
|
|
|
|
for node in node_list.items {
|
|
let name = node
|
|
.metadata
|
|
.name
|
|
.clone()
|
|
.unwrap_or_else(|| "unknown".to_string());
|
|
|
|
let ready = node
|
|
.status
|
|
.as_ref()
|
|
.and_then(|s| s.conditions.as_ref())
|
|
.and_then(|conditions| {
|
|
conditions
|
|
.iter()
|
|
.find(|c| c.type_ == "Ready")
|
|
.map(|c| c.status == "True")
|
|
})
|
|
.unwrap_or(false);
|
|
|
|
let version = node
|
|
.status
|
|
.as_ref()
|
|
.and_then(|s| s.node_info.as_ref())
|
|
.map(|info| info.kubelet_version.clone())
|
|
.unwrap_or_else(|| "unknown".to_string());
|
|
|
|
let internal_ip = node
|
|
.status
|
|
.as_ref()
|
|
.and_then(|s| s.addresses.as_ref())
|
|
.and_then(|addresses| {
|
|
addresses
|
|
.iter()
|
|
.find(|a| a.type_ == "InternalIP")
|
|
.map(|a| a.address.clone())
|
|
});
|
|
|
|
result.push(NodeStatus {
|
|
name,
|
|
ready,
|
|
version,
|
|
internal_ip,
|
|
});
|
|
}
|
|
|
|
Ok(result)
|
|
}
|
|
|
|
/// Gets detailed information about a specific node for diagnostics
|
|
pub async fn get_node_details(
|
|
&self,
|
|
node_name: &str,
|
|
) -> Result<NodeDetails, Box<dyn std::error::Error>> {
|
|
let nodes: Api<Node> = Api::all(self.inner().clone());
|
|
let node = nodes.get(node_name).await?;
|
|
|
|
// Conditions
|
|
let conditions = node
|
|
.status
|
|
.as_ref()
|
|
.and_then(|s| s.conditions.as_ref())
|
|
.map(|conds| {
|
|
conds
|
|
.iter()
|
|
.map(|c| NodeCondition {
|
|
type_: c.type_.clone(),
|
|
status: c.status.clone(),
|
|
reason: c.reason.clone(),
|
|
message: c.message.clone(),
|
|
})
|
|
.collect()
|
|
})
|
|
.unwrap_or_default();
|
|
|
|
// Resources - capacity
|
|
let capacity = node
|
|
.status
|
|
.as_ref()
|
|
.and_then(|s| s.capacity.as_ref())
|
|
.map(|c| NodeResources {
|
|
cpu: c.get("cpu").map(|q| q.0.clone()).unwrap_or_default(),
|
|
memory: c.get("memory").map(|q| q.0.clone()).unwrap_or_default(),
|
|
pods: c.get("pods").map(|q| q.0.clone()).unwrap_or_default(),
|
|
})
|
|
.unwrap_or(NodeResources {
|
|
cpu: "unknown".to_string(),
|
|
memory: "unknown".to_string(),
|
|
pods: "unknown".to_string(),
|
|
});
|
|
|
|
// Resources - allocatable
|
|
let allocatable = node
|
|
.status
|
|
.as_ref()
|
|
.and_then(|s| s.allocatable.as_ref())
|
|
.map(|a| NodeResources {
|
|
cpu: a.get("cpu").map(|q| q.0.clone()).unwrap_or_default(),
|
|
memory: a.get("memory").map(|q| q.0.clone()).unwrap_or_default(),
|
|
pods: a.get("pods").map(|q| q.0.clone()).unwrap_or_default(),
|
|
})
|
|
.unwrap_or(NodeResources {
|
|
cpu: "unknown".to_string(),
|
|
memory: "unknown".to_string(),
|
|
pods: "unknown".to_string(),
|
|
});
|
|
|
|
// Taints
|
|
let taints = node
|
|
.spec
|
|
.as_ref()
|
|
.and_then(|s| s.taints.as_ref())
|
|
.map(|t| {
|
|
t.iter()
|
|
.map(|taint| {
|
|
format!(
|
|
"{}={} (effect: {})",
|
|
taint.key,
|
|
taint.value.as_deref().unwrap_or(""),
|
|
taint.effect
|
|
)
|
|
})
|
|
.collect()
|
|
})
|
|
.unwrap_or_default();
|
|
|
|
// Labels
|
|
let labels = node
|
|
.metadata
|
|
.labels
|
|
.clone()
|
|
.unwrap_or_default()
|
|
.into_iter()
|
|
.collect::<Vec<_>>();
|
|
|
|
// Count pods on the node
|
|
let pods: Api<Pod> = Api::all(self.inner().clone());
|
|
let pod_list = pods.list(&ListParams::default()).await?;
|
|
let pod_count = pod_list
|
|
.items
|
|
.iter()
|
|
.filter(|pod| {
|
|
pod.spec
|
|
.as_ref()
|
|
.and_then(|s| s.node_name.as_ref())
|
|
.map(|n| n == node_name)
|
|
.unwrap_or(false)
|
|
})
|
|
.count();
|
|
|
|
let version = node
|
|
.status
|
|
.as_ref()
|
|
.and_then(|s| s.node_info.as_ref())
|
|
.map(|info| info.kubelet_version.clone())
|
|
.unwrap_or_else(|| "unknown".to_string());
|
|
|
|
Ok(NodeDetails {
|
|
name: node_name.to_string(),
|
|
conditions,
|
|
capacity,
|
|
allocatable,
|
|
taints,
|
|
labels,
|
|
pod_count,
|
|
version,
|
|
})
|
|
}
|
|
}
|