2
0
sunguroku 5 жил өмнө
parent
commit
57a408a482

+ 1 - 1
dashboard/src/main/home/dashboard/NamespaceSelector.tsx

@@ -25,7 +25,7 @@ export default class NamespaceSelector extends Component<PropsType, StateType> {
   }
   }
 
 
   updateOptions = () => {
   updateOptions = () => {
-    let { currentCluster, setCurrentError } = this.context;
+    let { currentCluster } = this.context;
 
 
     api.getNamespaces('<token>', { context: currentCluster }, {}, (err: any, res: any) => {
     api.getNamespaces('<token>', { context: currentCluster }, {}, (err: any, res: any) => {
       if (err) {
       if (err) {

+ 1 - 2
dashboard/src/main/home/dashboard/expanded-chart/ExpandedChart.tsx

@@ -154,8 +154,7 @@ export default class ExpandedChart extends Component<PropsType, StateType> {
       );
       );
     } else if (this.state.currentTab === 'logs') {
     } else if (this.state.currentTab === 'logs') {
       return (
       return (
-        <LogSection
-        />
+        <LogSection components={this.state.components}/>
       );
       );
     }
     }
 
 

+ 53 - 14
dashboard/src/main/home/dashboard/expanded-chart/LogSection.tsx

@@ -1,37 +1,75 @@
 import React, { Component } from 'react';
 import React, { Component } from 'react';
 import styled from 'styled-components';
 import styled from 'styled-components';
 import api from '../../../../shared/api';
 import api from '../../../../shared/api';
+import { ResourceType } from '../../../../shared/types';
 import { Context } from '../../../../shared/Context';
 import { Context } from '../../../../shared/Context';
 
 
 type PropsType = {
 type PropsType = {
+  components: ResourceType[],
 };
 };
 
 
 type StateType = {
 type StateType = {
-  logs: string
+  logs: string[]
+  podLabels: Record<string, string>[]
 };
 };
 
 
 export default class LogSection extends Component<PropsType, StateType> {
 export default class LogSection extends Component<PropsType, StateType> {
   state = {
   state = {
-    logs: ""
+    logs: [] as string[],
+    podLabels: [] as Record<string, string>[]
+  }
+  scrollRef = React.createRef<HTMLDivElement>()
+
+  ws = new WebSocket('ws://localhost:8080/api/k8s/default/pod/my-release-mongodb-77cfb78b98-t7xjq/logs?context=do-nyc1-k8s-1-18-8-do-1-nyc1-1603481399357')
+
+  scrollToBottom = () => {
+    this.scrollRef.current.scrollTop = this.scrollRef.current.scrollHeight
+  }
+
+  renderLogs = () => {
+    return this.state.logs.map(log => {
+      return <div>{log}</div>
+    })
+  }
+
+  renderPodTabs = () => {
+    console.log(this.state.podLabels)
   }
   }
 
 
   componentDidMount() {
   componentDidMount() {
-    const { currentCluster } = this.context;
-
-    api.getPodLogs('<token>', { context: currentCluster }, {}, (err: any, res: any) => {
-      if (err) {
-        this.setState({logs: "ERROR"})
-        // this.setState({ namespaceOptions: [{ label: 'All', value: '' }] });
-      } else {
-        this.setState({logs: res.data});
+    const { components } = this.props;
+
+    components.forEach((c: ResourceType) => {
+      switch(c.Kind) {
+        case "Pod":
+          this.setState({podLabels: [...this.state.podLabels, c.RawYAML.metadata.labels]})
       }
       }
-    });
+    })
+
+    this.ws.onopen = () => {
+      console.log('connected to websocket')
+    }
+
+    this.ws.onmessage = evt => {
+      this.setState({ logs: [...this.state.logs, evt.data] }, () => {
+        this.scrollToBottom()
+      })
+    }
+    // api.getPodLogs('<token>', { context: currentCluster }, {}, (err: any, res: any) => {
+    //   if (err) {
+    //     this.setState({logs: "ERROR"})
+    //     // this.setState({ namespaceOptions: [{ label: 'All', value: '' }] });
+    //   } else {
+    //     this.setState({logs: res.data});
+    //   }
+    // });
   }
   }
 
 
   render() {
   render() {
     return (
     return (
-      <StyledLogSection>
-        {this.state.logs}
+      <StyledLogSection ref={this.scrollRef}>
+        {this.renderPodTabs()}
+        {this.renderLogs()}
       </StyledLogSection>
       </StyledLogSection>
     );
     );
   }
   }
@@ -45,5 +83,6 @@ const StyledLogSection = styled.div`
   height: 100%;
   height: 100%;
   background: #202227;
   background: #202227;
   position: relative;
   position: relative;
-  padding: 20px;
+  padding: 0px;
+  user-select: text;
 `;
 `;

+ 3 - 3
dashboard/src/shared/types.tsx

@@ -34,7 +34,7 @@ export interface ResourceType {
   ID: number,
   ID: number,
   Kind: string,
   Kind: string,
   Name: string,
   Name: string,
-  RawYAML: Object,
+  RawYAML: any,
   Relations: any
   Relations: any
 }
 }
 
 
@@ -42,7 +42,7 @@ export interface NodeType {
   id: number,
   id: number,
   name: string,
   name: string,
   kind: string,
   kind: string,
-  RawYAML?: Object,
+  RawYAML?: any,
   x: number,
   x: number,
   y: number,
   y: number,
   w: number,
   w: number,
@@ -62,4 +62,4 @@ export enum StorageType {
   Secret = 'secret',
   Secret = 'secret',
   ConfigMap = 'configmap',
   ConfigMap = 'configmap',
   Memory = 'memory'
   Memory = 'memory'
-}
+}

+ 19 - 10
internal/kubernetes/agent.go

@@ -1,7 +1,7 @@
 package kubernetes
 package kubernetes
 
 
 import (
 import (
-	"bytes"
+	"bufio"
 	"context"
 	"context"
 	"fmt"
 	"fmt"
 	"io"
 	"io"
@@ -31,22 +31,31 @@ func (a *Agent) ListNamespaces() (*v1.NamespaceList, error) {
 // GetPodLogs streams real-time logs from a given pod.
 // GetPodLogs streams real-time logs from a given pod.
 func (a *Agent) GetPodLogs(namespace string, name string, conn *websocket.Conn) error {
 func (a *Agent) GetPodLogs(namespace string, name string, conn *websocket.Conn) error {
 	// follow logs
 	// follow logs
-	podLogOpts := v1.PodLogOptions{Follow: true}
+	tails := int64(30)
+	podLogOpts := v1.PodLogOptions{
+		Follow:    true,
+		TailLines: &tails,
+	}
 	req := a.Clientset.CoreV1().Pods(namespace).GetLogs(name, &podLogOpts)
 	req := a.Clientset.CoreV1().Pods(namespace).GetLogs(name, &podLogOpts)
 	podLogs, err := req.Stream(context.TODO())
 	podLogs, err := req.Stream(context.TODO())
-
 	if err != nil {
 	if err != nil {
 		return fmt.Errorf("Cannot open log stream for pod %s", name)
 		return fmt.Errorf("Cannot open log stream for pod %s", name)
 	}
 	}
 	defer podLogs.Close()
 	defer podLogs.Close()
 
 
-	buf := new(bytes.Buffer)
-	_, err = io.Copy(buf, podLogs)
-	log := buf.String()
+	r := bufio.NewReader(podLogs)
+	for {
+		bytes, err := r.ReadBytes('\n')
 
 
-	if writeErr := conn.WriteMessage(websocket.TextMessage, []byte(log)); writeErr != nil {
-		return writeErr
-	}
+		if writeErr := conn.WriteMessage(websocket.TextMessage, bytes); writeErr != nil {
+			return writeErr
+		}
 
 
-	return err
+		if err != nil {
+			if err != io.EOF {
+				return err
+			}
+			return nil
+		}
+	}
 }
 }