Init
This commit is contained in:
181
src/k8s/nodes.rs
Normal file
181
src/k8s/nodes.rs
Normal file
@@ -0,0 +1,181 @@
|
||||
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,
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user