Ver Fonte

pod status aggregates container statuses

sunguroku há 5 anos atrás
pai
commit
29008d5f2f

+ 63 - 27
dashboard/src/main/home/cluster-dashboard/expanded-chart/status/ControllerTab.tsx

@@ -4,36 +4,40 @@ import { kindToIcon } from '../../../../../shared/rosettaStone';
 import api from '../../../../../shared/api';
 import { Context } from '../../../../../shared/Context';
 
-interface Pod {
-  namespace?: string;
-  name?: string;
-
-}
-
 type PropsType = {
   controller: any,
-  selectedPod: Pod,
+  selectedPod: any,
   selectPod: Function,
 };
 
 type StateType = {
   expanded: boolean,
-  pods: Pod[],
+  pods: any[],
+  raw: any[],
 };
 
 // Controller tab in log section that displays list of pods on click.
 export default class ControllerTab extends Component<PropsType, StateType> {
   state = {
     expanded: false,
-    pods: [] as Pod[],
+    pods: [] as any[],
+    raw: [] as any[],
   }
 
-  // Handle previewing old revisions
-//   componentDidUpdate(prevProps: PropsType) {
-//     if (prevProps.resource.RawYAML !== this.props.resource.RawYAML) {
-    //   this.setState({ RawYAML: yaml.dump(this.props.resource.RawYAML) });
-//     }
-//   }
+  getAvailability = (kind: string, c: any) => {
+    switch (kind?.toLowerCase()) {
+      case "deployment":
+      case "replicaset":
+        return [
+          c.status?.availableReplicas || c.status?.replicas - c.status?.unavailableReplicas, 
+          c.status?.replicas
+        ]
+      case "statefulset":
+       return [c.status?.readyReplicas, c.status?.replicas]
+      case "daemonset":
+        return [c.status?.numberAvailable, c.status?.desiredNumberScheduled]
+      }
+  }
 
   renderIcon = (kind: string) => {
 
@@ -49,19 +53,48 @@ export default class ControllerTab extends Component<PropsType, StateType> {
     );
   }
 
+  getPodStatus = (status: any) => {
+    if (status?.phase == 'Pending') {
+      return 'waiting'
+    }
+
+    if (status?.phase == 'Failed') {
+      return 'failed'
+    }
+
+    if (status?.phase == 'Running') {
+      let collatedStatus = 'running';
+
+      status.containerStatuses.forEach((s: any) => {
+        if (s.state?.waiting) {
+          collatedStatus = 'waiting'
+        } else if (s.state?.terminated) {
+          collatedStatus = 'failed'
+          throw {};
+        }
+      })
+      return collatedStatus;
+    }
+  }
+
   renderExpanded = () => {
     if (this.state.expanded) {
       return (
         <ExpandWrapper>
             {
-              this.state.pods.map((pod) => {
+              this.state.raw.map((pod) => {
+                let status = this.getPodStatus(pod.status)
                 return (
                   <Tab 
-                    key={pod.name}
-                    selected={(this.props.selectedPod.name === pod.name)}
+                    key={pod.metadata?.name}
+                    selected={(this.props.selectedPod?.metadata?.name === pod?.metadata?.name)}
                     onClick={() => {this.props.selectPod(pod)}}
                   > 
-                    {pod.name} 
+                    {pod.metadata?.name}
+                    <Status>
+                      <StatusColor status={status} />
+                      {status}
+                    </Status>
                   </Tab>)
               })
             }
@@ -102,18 +135,19 @@ export default class ControllerTab extends Component<PropsType, StateType> {
       let pods = res?.data?.map((pod: any) => {
         return {
           namespace: pod?.metadata?.namespace, 
-          name: pod?.metadata?.name
+          name: pod?.metadata?.name,
+          phase: pod?.status?.phase,
         }
       })
       console.log(res.data)
-      this.setState({ pods })
+      this.setState({ pods, raw: res.data })
     })
   }
 
   render() {
     let { controller } = this.props;
-    console.log(controller)
-    let status = 'running'
+    let [available, total] = this.getAvailability(controller.kind, controller);
+    let status = (available == total) ? 'running' : 'waiting'
     return (
       <StyledResourceItem>
         <ResourceHeader
@@ -135,7 +169,7 @@ export default class ControllerTab extends Component<PropsType, StateType> {
           </Metadata>
           <Status>
             <StatusColor status={status} />
-            3/{controller.status.replicas}
+            {available}/{total}
           </Status>
           </Info>
         </ResourceHeader>
@@ -214,13 +248,15 @@ const StatusColor = styled.div`
 `;
 
 const Tab = styled.div`
+  width: 100%;
+  height: 100%;
+  display: flex;
   align-items: center;
+  justify-content: space-between;
   color: ${(props: {selected: boolean}) => props.selected ? 'white' : '#ffffff66'};
   background: ${(props: {selected: boolean}) => props.selected ? '#ffffff18' : '##ffffff11'};
-  height: 100%;
-  justify-content: center;
   font-size: 13px;
-  padding: 25px 13px;
+  padding: 20px 12px 20px 45px;
   text-shadow: 0px 0px 8px none;
   cursor: pointer;
   :hover {

+ 19 - 11
dashboard/src/main/home/cluster-dashboard/expanded-chart/status/Logs.tsx

@@ -2,13 +2,8 @@ import React, { Component } from 'react';
 import styled from 'styled-components';
 import { Context } from '../../../../../shared/Context';
 
-interface Pod {
-  namespace?: string;
-  name?: string;
-}
-
 type PropsType = {
-  selectedPod: Pod,
+  selectedPod: any,
 };
 
 type StateType = {
@@ -31,8 +26,11 @@ export default class Logs extends Component<PropsType, StateType> {
 
   renderLogs = () => {
     let { selectedPod } = this.props;
-    if (!selectedPod.name) {
-      return <div>no bueno, select pod pl0x</div>
+    if (!selectedPod?.metadata?.name) {
+      return <Message>Please select a pod to view its logs.</Message>
+    }
+    if (this.state.logs.length == 0) {
+      return <Message>No logs to display from this pod.</Message>
     }
     return this.state.logs.map((log, i) => {
         return <div key={i}>{log}</div>
@@ -42,9 +40,9 @@ export default class Logs extends Component<PropsType, StateType> {
   componentDidMount() {
     let { currentCluster, currentProject } = this.context;
     let { selectedPod } = this.props;
-    if (!selectedPod.name) return
+    if (!selectedPod.metadata?.name) return
 
-    let ws = new WebSocket(`ws://localhost:8080/api/projects/${currentProject.id}/k8s/${selectedPod.namespace}/pod/${selectedPod.name}/logs?cluster_id=${currentCluster.id}&service_account_id=${currentCluster.service_account_id}`)
+    let ws = new WebSocket(`ws://localhost:8080/api/projects/${currentProject.id}/k8s/${selectedPod?.metadata?.namespace}/pod/${selectedPod?.metadata?.name}/logs?cluster_id=${currentCluster.id}&service_account_id=${currentCluster.service_account_id}`)
 
     this.setState({ ws }, () => {
       if (!this.state.ws) return;
@@ -92,4 +90,14 @@ const LogStream = styled.div`
   user-select: text;
   overflow: auto;
   border-radius: 5px;
-`;
+`;
+
+const Message = styled.div`
+  display: flex;
+  height: 100%;
+  width: 100%;
+  align-items: center;
+  justify-content: center;
+  color: #ffffff44;
+  font-size: 14px;
+`

+ 11 - 16
dashboard/src/main/home/cluster-dashboard/expanded-chart/status/StatusSection.tsx

@@ -6,11 +6,6 @@ import ControllerTab from './ControllerTab';
 import { Context } from '../../../../../shared/Context';
 import { ChartType, StorageType } from '../../../../../shared/types';
 
-interface Pod {
-  namespace?: string;
-  name?: string;
-}
-
 type PropsType = {
   selectors: string[],
   currentChart: ChartType,
@@ -18,30 +13,29 @@ type PropsType = {
 
 type StateType = {
   logs: string[]
-  pods: Pod[],
-  selectedPod: Pod,
+  pods: any[],
+  selectedPod: any,
   controllers: any[],
 };
 
 export default class StatusSection extends Component<PropsType, StateType> {
   state = {
     logs: [] as string[],
-    pods: [] as Pod[],
-    selectedPod: {} as Pod,
+    pods: [] as any[],
+    selectedPod: {} as any,
     controllers: [] as any[],
   }
 
   renderLogs = () => {
-    return <Logs key={this.state.selectedPod?.name} selectedPod={this.state.selectedPod} />
+    return <Logs 
+      key={this.state.selectedPod?.metadata?.name} 
+      selectedPod={this.state.selectedPod} 
+    />
   }
 
-  selectPod = (pod: Pod) => {
-    let select = { 
-      namespace: pod.namespace, 
-      name: pod.name,
-    }
+  selectPod = (pod: any) => {
     this.setState({
-      selectedPod: select
+      selectedPod: pod
     })
   }
 
@@ -81,6 +75,7 @@ export default class StatusSection extends Component<PropsType, StateType> {
   componentDidMount() {
     const { selectors, currentChart } = this.props;
     let { currentCluster, currentProject, setCurrentError } = this.context;
+
     api.getChartControllers('<token>', {
       namespace: currentChart.namespace,
       cluster_id: currentCluster.id,