Kaynağa Gözat

Finished refactor of controller tab

jnfrati 4 yıl önce
ebeveyn
işleme
7aa0fcdfd0

+ 101 - 5
dashboard/src/main/home/cluster-dashboard/expanded-chart/status/ControllerTab.tsx

@@ -11,7 +11,7 @@ import { Context } from "shared/Context";
 import { ChartType } from "shared/types";
 import ResourceTab from "components/ResourceTab";
 import ConfirmOverlay from "components/ConfirmOverlay";
-import { useWebsockets } from "shared/hooks/useWebsockets";
+import { NewWebsocketOptions, useWebsockets } from "shared/hooks/useWebsockets";
 import PodRow from "./PodRow";
 
 type PropsType = {
@@ -399,6 +399,7 @@ const ControllerTabFC: React.FunctionComponent<PropsType> = ({
   selectedPod,
 }) => {
   const [pods, setPods] = useState<ControllerTabPodType[]>([]);
+  const [rawPodList, setRawPodList] = useState<any[]>([]);
   const [podPendingDelete, setPodPendingDelete] = useState<any>(null);
   const [available, setAvailable] = useState<number>(null);
   const [total, setTotal] = useState<number>(null);
@@ -407,7 +408,12 @@ const ControllerTabFC: React.FunctionComponent<PropsType> = ({
   const { currentCluster, currentProject, setCurrentError } = useContext(
     Context
   );
-  const {} = useWebsockets();
+  const {
+    newWebsocket,
+    openWebsocket,
+    closeAllWebsockets,
+    closeWebsocket,
+  } = useWebsockets();
 
   const currentSelectors = useMemo(() => {
     if (controller.kind.toLowerCase() == "job" && selectors) {
@@ -459,18 +465,45 @@ const ControllerTabFC: React.FunctionComponent<PropsType> = ({
         });
 
       setPods(newPods);
+      setRawPodList(data);
       if (!userSelectedPod) {
         let status = getPodStatus(newPods[0].status);
         status === "failed" &&
           newPods[0].status?.message &&
           setPodError(newPods[0].status?.message);
-        selectPod(newPods[0]);
+        handleSelectPod(newPods[0], data);
       }
     } catch (error) {}
   };
 
+  const handleSelectPod = (pod: ControllerTabPodType, rawList?: any[]) => {
+    console.log(rawPodList);
+    const rawPod = [...rawPodList, ...(rawList || [])].find(
+      (rawPod) => rawPod?.metadata?.name === pod?.name
+    );
+    selectPod(rawPod);
+  };
+
+  const currentSelectedPod = useMemo(() => {
+    const pod = selectedPod;
+    const replicaSetName =
+      Array.isArray(pod?.metadata?.ownerReferences) &&
+      pod?.metadata?.ownerReferences[0]?.name;
+    return {
+      namespace: pod?.metadata?.namespace,
+      name: pod?.metadata?.name,
+      phase: pod?.status?.phase,
+      status: pod?.status,
+      replicaSetName,
+    } as ControllerTabPodType;
+  }, [selectedPod]);
+
   useEffect(() => {
     updatePods();
+    [controller?.kind, "pod"].forEach((kind) => {
+      setupWebsocket(kind, controller?.metadata?.uid);
+    });
+    () => closeAllWebsockets();
   }, [currentSelectors, controller, currentCluster, currentProject]);
 
   const currentControllerStatus = useMemo(() => {
@@ -567,6 +600,69 @@ const ControllerTabFC: React.FunctionComponent<PropsType> = ({
     }
   }, [pods]);
 
+  const getAvailability = (kind: string, c: any) => {
+    switch (kind?.toLowerCase()) {
+      case "deployment":
+      case "replicaset":
+        return [
+          c.status?.availableReplicas ||
+            c.status?.replicas - c.status?.unavailableReplicas ||
+            0,
+          c.status?.replicas || 0,
+        ];
+      case "statefulset":
+        return [c.status?.readyReplicas || 0, c.status?.replicas || 0];
+      case "daemonset":
+        return [
+          c.status?.numberAvailable || 0,
+          c.status?.desiredNumberScheduled || 0,
+        ];
+      case "job":
+        return [1, 1];
+    }
+  };
+
+  const setupWebsocket = (kind: string, controllerUid: string) => {
+    let apiEndpoint = `/api/projects/${currentProject.id}/k8s/${kind}/status?cluster_id=${currentCluster.id}`;
+    if (kind == "pod" && currentSelectors) {
+      apiEndpoint += `&selectors=${currentSelectors[0]}`;
+    }
+
+    const options: NewWebsocketOptions = {};
+    options.onopen = () => {
+      console.log("connected to websocket");
+    };
+
+    options.onmessage = (evt: MessageEvent) => {
+      let event = JSON.parse(evt.data);
+      let object = event.Object;
+      object.metadata.kind = event.Kind;
+
+      // update pods no matter what if ws message is a pod event.
+      // If controller event, check if ws message corresponds to the designated controller in props.
+      if (event.Kind != "pod" && object.metadata.uid !== controllerUid) return;
+
+      if (event.Kind != "pod") {
+        let [available, total] = getAvailability(object.metadata.kind, object);
+        setAvailable(available);
+        setTotal(total);
+      }
+      updatePods();
+    };
+
+    options.onclose = () => {
+      console.log("closing websocket");
+    };
+
+    options.onerror = (err: ErrorEvent) => {
+      console.log(err);
+      closeWebsocket(kind);
+    };
+
+    newWebsocket(kind, apiEndpoint, options);
+    openWebsocket(kind);
+  };
+
   return (
     <ResourceTab
       label={controller.kind}
@@ -582,7 +678,7 @@ const ControllerTabFC: React.FunctionComponent<PropsType> = ({
           <PodRow
             key={i}
             pod={pod}
-            isSelected={selectedPod?.name === pod?.name}
+            isSelected={currentSelectedPod?.name === pod?.name}
             podStatus={status}
             isLastItem={i === pods.length - 1}
             onTabClick={() => {
@@ -590,7 +686,7 @@ const ControllerTabFC: React.FunctionComponent<PropsType> = ({
               status === "failed" &&
                 pod.status?.message &&
                 setPodError(pod.status?.message);
-              selectPod(pod);
+              handleSelectPod(pod);
               setUserSelectedPod(true);
             }}
             onDeleteClick={() => setPodPendingDelete(pod)}