fleetmod 0.1.1

Kubernetes model for fleet
Documentation
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use chrono::{DateTime, Local};

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "lowercase")]
pub struct Node {
    #[serde(rename = "apiVersion")]
    pub api_version: String,
    pub kind: String,
    pub metadata: NodeMetadata,
    pub spec: NodeSpec,
    pub status: NodeStatus,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "lowercase")]
pub struct NodeSpec {
    #[serde(rename = "podCIDR")]
    pub pod_cidr: String,
    pub taints: Option<Vec<Taint>>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "lowercase")]
pub struct Taint {
    pub key: String,
    pub value: String,
    pub effect: String,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "lowercase")]
pub struct NodeMetadata {
    pub name: String,
    pub role: String,
    pub labels: Option<HashMap<String, String>>,
    pub annotations: Option<HashMap<String, String>>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "lowercase")]
pub struct NodeStatus {
    pub capacity: Capacity,
    pub allocatable: Allocatable,
    pub condition: Option<Vec<Condition>>,
    pub addresses: Option<Vec<Address>>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "lowercase")]
pub struct Capacity {
    pub cpu: Option<String>,
    pub memory: Option<String>,
    pub disk: Option<String>,
    pub pods: Option<String>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "lowercase")]
pub struct Allocatable {
    pub cpu: Option<String>,
    pub memory: Option<String>,
    pub disk: Option<String>,
    pub pods: Option<String>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "lowercase")]
pub struct Condition {
    #[serde(rename = "type")]
    pub node_type: Option<String>,
    pub status: Option<String>,
    #[serde(rename = "lastHeartbeatTime")]
    pub last_heartbeat_time: Option<DateTime<Local>>,
    pub reasion: Option<String>,
    pub message: Option<String>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "lowercase")]
pub struct Address {
    #[serde(rename = "type")]
    pub address_type: String,
    pub address: String,
}

#[cfg(test)]
mod tests {
    use super::*; // 导入主模块中的定义

    #[test]
    fn test_node_deserialization() {
        // 测试用的 Pod YAML 示例
        let node_yaml = r#"
{
  "apiVersion": "v1",
  "kind": "Node",
  "metadata": {
    "name": "node-name",
    "role": "master",
    "labels": {
      "kubernetes.io/hostname": "node-name",
      "beta.kubernetes.io/os": "linux",
      "beta.kubernetes.io/arch": "amd64"
    },
    "annotations": {
      "kubeadm.alpha.kubernetes.io/cri-socket": "/var/run/dockershim.sock"
    }
  },
  "spec": {
    "podCIDR": "10.244.0.0/24",
    "taints": [
      {
        "key": "key1",
        "value": "value1",
        "effect": "NoSchedule"
      }
    ]
  },
  "status": {
    "capacity": {
      "cpu": "4",
      "memory": "16384Mi",
      "ephemeral-storage": "1024Gi",
      "pods": "110"
    },
    "allocatable": {
      "cpu": "3",
      "memory": "12288Mi",
      "ephemeral-storage": "800Gi",
      "pods": "100"
    },
    "conditions": [
      {
        "type": "Ready",
        "status": "True",
        "lastHeartbeatTime": "2024-12-10T12:34:56Z",
        "lastTransitionTime": "2024-12-10T12:34:56Z",
        "reason": "KubeletReady",
        "message": "kubelet is posting ready status"
      }
    ],
    "addresses": [
      {
        "type": "InternalIP",
        "address": "192.168.1.1"
      },
      {
        "type": "Hostname",
        "address": "node-name"
      }
    ]
  }
}

"#;

        let node: Node = serde_yaml::from_str(node_yaml).expect("Failed to parse YAML");

        assert_eq!(node.api_version, "v1");
        assert_eq!(node.kind, "Node");
        assert_eq!(node.metadata.name, "node-name");
        assert_eq!(node.metadata.labels.clone().unwrap().len(), 3);
        assert_eq!(node.spec.pod_cidr, "10.244.0.0/24");
        assert_eq!(node.spec.taints.clone().unwrap().len(), 1);
        assert_eq!(node.status.capacity.cpu.clone().unwrap(), "4");
        let addresses = node.status.addresses.clone().unwrap(); // 如果是 None,会 panic
        assert_eq!(addresses[0].address, "192.168.1.1");
        println!("{:#?}", node);
    }
}