fleetmod 0.1.1

Kubernetes model for fleet
Documentation
/**

* Copyright(2024,)Institute of Software, Chinese Academy of Sciences
* author: jiangliuwei@iscas.ac.cn
* since: 0.1.0
*
**/
use serde::{Deserialize, Serialize};
use chrono::{DateTime, Local};
use crate::metadata::medadata::Metadata;
use crate::pod::pod::Pod;

#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum EvenType {
    Normal,
    Warning,
    Error,
    Painic,
}

#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct Event {
    #[serde(rename = "apiVersion")]
    pub api_version: String,
    pub kind: String,
    pub metadata: Metadata,
    #[serde(rename = "involvedObject")]
    pub involved_object: Option<ObjectReference>,
    pub reason: Option<String>,
    pub message: Option<String>,
    pub source: Option<EventSource>,
    #[serde(rename = "lastTimestamp")]
    pub last_timestamp: Option<DateTime<Local>>,
    #[serde(rename = "type")]
    pub event_type: Option<EvenType>,
    #[serde(rename = "reportingInstance")]
    pub reporting_instance: Option<String>,
}

#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct ObjectReference {
    pub kind: String,
    pub namespace: String,
    pub name: String,
    pub uid: String,
    #[serde(rename = "apiVersion")]
    pub api_version: Option<String>,
    #[serde(rename = "resourceVersion")]
    pub resource_version: Option<String>,
}

#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct EventSource {
    pub component: String,
    pub host: Option<String>,
}


impl Event {
    #[allow(dead_code)]
    fn new_pod_event(pod: Pod, event_type: EvenType, comment: String, reason: String, message: String) -> Self {
        Event {
            api_version: "v1".to_string(),
            kind: "Event".to_string(),
            metadata: Metadata {
                name: format!("{}.{}", pod.metadata.name, crate::generate_uid_to_cutter()),
                namespace: pod.metadata.namespace.clone(),
                labels: None,
                annotations: None,
                uid: Some(crate::generate_uid()),
                resource_version: Some(crate::generate_resource_version()),
                creation_timestamp: Some(Local::now()),
            },
            involved_object: Some(ObjectReference {
                kind: pod.kind,
                namespace: pod.metadata.namespace,
                name: pod.metadata.name,
                uid: pod.metadata.uid.unwrap(),
                api_version: Some(pod.api_version),
                resource_version: pod.metadata.resource_version,
            }),
            reason: Some(reason),
            message: Some(message),
            source: Some(EventSource {
                component: comment.clone(),
                host: None,
            }),
            last_timestamp: Some(Local::now()),
            event_type: Some(event_type),
            reporting_instance: Some(comment),
        }
    }
}


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

    #[test]
    fn test_event_deserialization() {
        let event_yaml = r#"
apiVersion: v1
kind: Event
count: 1460
involvedObject:
  apiVersion: v1
  fieldPath: spec.containers{test}
  kind: Pod
  name: test-6c8847f6c7-qffrj
  namespace: default
  resourceVersion: "853"
  uid: 6be77998-98f6-4e68-b171-ebe7c51238d2
lastTimestamp: "2024-12-10T11:51:15Z"
message: Back-off pulling image "registry.cn-hangzhou.aliyuncs.com/liuliu-public/test:latest123"
metadata:
  creationTimestamp: "2024-12-10T06:21:07Z"
  name: test-6c8847f6c7-qffrj.180fbc869d46c773
  namespace: default
  resourceVersion: "7123"
  uid: 3291a46a-e9a2-4bcf-86dd-48b923c51c10
reason: BackOff
reportingComponent: kubelet
reportingInstance: vm-8-15-centos
source:
  component: kubelet
  host: vm-8-15-centos
type: Normal
"#;

        let event: Event = serde_yaml::from_str(event_yaml).expect("Failed to parse YAML");

        assert_eq!(event.api_version, "v1");
        assert_eq!(event.kind, "Event");
        assert_eq!(event.metadata.name, "test-6c8847f6c7-qffrj.180fbc869d46c773");
        assert_eq!(event.metadata.namespace, "default");
        assert_eq!(event.involved_object.clone().unwrap().api_version.unwrap(), "v1");
        assert_eq!(event.involved_object.clone().unwrap().kind, "Pod");
        let creation_time = event.metadata.creation_timestamp;
        assert_eq!(
            creation_time.unwrap(),
            "2024-12-10T06:21:07Z"
                .parse::<DateTime<Local>>()
                .unwrap()
        );
        println!("{:#?}", event);
    }
    #[test]
    fn test_new_pod_event(){

        // 测试用的 Pod YAML 示例
        let pod_yaml = r#"
apiVersion: v1
kind: Pod
metadata:
  name: example-pod
  namespace: default
  labels:
    app: my-app
  creationTimestamp: 2024-12-10T08:00:00+08:00
spec:
  nodeName: my-node
  hostname: my-hostname
  hostAliases:
  - ip: "127.0.0.1"
    hostnames:
    - "my-local-host"
    - "another-host"
  containers:
  - name: example-container
    image: example-image:latest
    imagePullPolicy: IfNotPresent
    command: ["nginx"]
    args: ["-g", "daemon off;"]
    workingDir: /usr/share/nginx/html
    ports:
    - name: http
      containerPort: 80
      protocol: TCP
    - name: https
      containerPort: 443
      protocol: TCP
    env:
    - name: ENV_MODE
      value: production
    - name: ENV_VERSION
      valueFrom:
        fieldRef:
          fieldPath: metadata.name
    resources:
      requests:
        memory: "128Mi"
        cpu: "250m"
      limits:
        memory: "512Mi"
        cpu: "1"
    volumeMounts:
    - name: config-volume
      mountPath: /etc/nginx/conf.d
      readOnly: true
    - name: data-volume
      mountPath: /usr/share/nginx/html
    - name: data-host-volume
      mountPath: /usr/share/nginx/a.txt
    volumeDevices:
    - name: device-volume
      devicePath: /dev/sdb
    securityContext:
      runAsUser: 1000
      runAsGroup: 1000
      readOnlyRootFilesystem: true
      allowPrivilegeEscalation: true
      privileged: true
  volumes:
  - name: example-volume
    configMap:
      name: nginx-config
  - name: data-volume
    emptyDir: {}
  - name: device-volume
    hostPath:
      path: /dev/sdb
      type: Directory
  - name: device-volume
    hostPath:
      path: /dev/sdb
      type: Directory
status:
  phase: Pending
  message: begin handle
  podIP: 10.42.0.9
  podIPs:
  - ip: 10.42.0.9
"#;

        let mut pod: Pod = serde_yaml::from_str(pod_yaml).expect("Failed to parse YAML");
        pod.fill_pod_defaults();

        // 调用 new_pod_event 方法生成事件
        let event = Event::new_pod_event(pod.clone(), EvenType::Warning, "fleet-scheduler".to_string(), "backOff".to_string(), "get node failed".to_string());
        assert_eq!(event.metadata.name.starts_with(&pod.metadata.name), true);
        assert_eq!(event.metadata.namespace, pod.metadata.namespace);
        assert!(event.metadata.uid.is_some());
        assert!(event.metadata.resource_version.is_some());
        assert!(event.metadata.creation_timestamp.is_some());

        // 验证 involved_object
        assert!(event.involved_object.is_some());
        let involved_object = event.involved_object.unwrap();
        assert_eq!(involved_object.kind, pod.kind);
        assert_eq!(involved_object.namespace, pod.metadata.namespace);
        assert_eq!(involved_object.name, pod.metadata.name);
        assert_eq!(involved_object.uid, pod.metadata.uid.unwrap());
        assert_eq!(involved_object.api_version.unwrap(), pod.api_version);
        assert_eq!(involved_object.resource_version.unwrap(), pod.metadata.resource_version.unwrap());

        // 验证 reason 和 message
        assert_eq!(event.reason.unwrap(), "backOff");
        assert_eq!(event.message.unwrap(), "get node failed");

        // 验证 source
        assert!(event.source.is_some());
        let source = event.source.unwrap();
        assert_eq!(source.component, "fleet-scheduler");
        assert_eq!(source.host, None);

        // 验证 last_timestamp
        assert!(event.last_timestamp.is_some());

        // 验证 event_type
        assert!(event.event_type.is_some());
        assert!(matches!(event.event_type.unwrap(), EvenType::Warning));

        // 验证 reporting_instance
        assert_eq!(event.reporting_instance.unwrap(), "fleet-scheduler");

    }



}