2
0
Эх сурвалжийг харах

add unit in form default values, provisioning boilerplate

sunguroku 5 жил өмнө
parent
commit
3c7a2bffae

+ 1 - 0
dashboard/src/components/values-form/ValuesForm.tsx

@@ -27,6 +27,7 @@ export default class ValuesForm extends Component<PropsType, StateType> {
   getInputValue = (item: FormElement) => {
     let key = item.name || item.variable;
     let value = this.props.metaState[key];
+    
     if (item.settings && item.settings.unit && value) {
       value = value.split(item.settings.unit)[0]
     }

+ 2 - 1
dashboard/src/components/values-form/ValuesWrapper.tsx

@@ -40,7 +40,8 @@ export default class ValuesWrapper extends Component<PropsType, StateType> {
 
             // If no name is assigned use values.yaml variable as identifier
             let key = item.name || item.variable;
-            let def = (item.value && item.value[0]) || (item.settings && item.settings.default);
+            let def = item.settings && item.settings.unit ? `${item.settings.default}${item.settings.unit}` : item.settings.default
+            def = (item.value && item.value[0]) || def;
 
             // Handle add to list of required fields
             if (item.required) {

+ 190 - 3
dashboard/src/main/home/provisioner/Provisioner.tsx

@@ -1,25 +1,212 @@
 import React, { Component } from 'react';
 import styled from 'styled-components';
+import posthog from 'posthog-js';
 
-type PropsType = {
-};
+import api from 'shared/api';
+import { Context } from 'shared/Context';
+import ansiparse from 'shared/ansiparser'
+import loading from 'assets/loading.gif';
+import warning from 'assets/warning.png';
+import { InfraType } from 'shared/types';
+
+import Helper from 'components/values-form/Helper';
+import InfraStatuses from './InfraStatuses';
+import { RouteComponentProps, withRouter } from "react-router";
+import { Link } from "react-router-dom";
+
+type PropsType = RouteComponentProps & {};
 
 type StateType = {
+  error: boolean,
+  logs: string[],
+  websockets: any[],
+  maxStep : Record<string, number>,
+  currentStep: Record<string, number>,
+  triggerEnd: boolean,
+  infras: InfraType[],
 };
 
-export default class Provisioner extends Component<PropsType, StateType> {
+class Provisioner extends Component<PropsType, StateType> {
   state = {
+    error: false,
+    logs: [] as string[],
+    websockets : [] as any[],
+    maxStep: {} as Record<string, any>,
+    currentStep: {} as Record<string, number>,
+    triggerEnd: false,
+    infras: [] as InfraType[],
+  }
+
+  parentRef = React.createRef<HTMLDivElement>()
+
+  scrollToBottom = (smooth: boolean) => {
+    if (smooth) {
+      this.parentRef.current.lastElementChild.scrollIntoView({ behavior: "smooth" })
+    } else {
+      this.parentRef.current.lastElementChild.scrollIntoView({ behavior: "auto" })
+    }
+  }
+
+  isJSON = (str: string) => {
+    try {
+      JSON.parse(str);
+    } catch (e) {
+      return false;
+    }
+    return true;
+  }
+
+  setupWebsocket = (ws: WebSocket, infra: any) => {
+    ws.onopen = () => {
+      console.log('connected to websocket')
+    }
+
+    ws.onmessage = (evt: MessageEvent) => {
+      let event = JSON.parse(evt.data);
+      let validEvents = [] as any[];
+      let err = null;
+      
+      for (var i = 0; i < event.length; i++) {
+        let msg = event[i];
+        if (msg["Values"] && msg["Values"]["data"] && this.isJSON(msg["Values"]["data"])) { 
+          let d = JSON.parse(msg["Values"]["data"]);
+
+          if (d["kind"] == "error") {
+            err = d["log"];
+            break;
+          }
+
+          // add only valid events
+          if (d["log"] != null && d["created_resources"] != null && d["total_resources"] != null) {
+            validEvents.push(d);
+          }
+        }
+      }
+
+      if (err) {
+        posthog.capture('Provisioning Error', {error: err});
+
+        let e = ansiparse(err).map((el: any) => {
+          return el.text;
+        })
+
+        let index = this.state.infras.findIndex(el => el.kind === infra.kind)
+        infra.status = "error"
+        let infras = this.state.infras
+        infras[index] = infra
+        this.setState({ logs: [...this.state.logs, ...e], error: true, infras });
+        return;
+      }
+
+      if (validEvents.length == 0) {
+        return;
+      }
+
+      if (!this.state.maxStep[infra.kind] || !this.state.maxStep[infra.kind]["total_resources"]) {
+        this.setState({
+          maxStep: {
+            ...this.state.maxStep,
+            [infra.kind] : validEvents[validEvents.length - 1]["total_resources"]
+          }
+        })
+      }
+      
+      let logs = [] as any[]
+      validEvents.forEach((e: any) => {
+        logs.push(...ansiparse(e["log"]))
+      })
+
+      logs = logs.map((log: any) => {
+        return log.text
+      })
+
+      this.setState({ 
+        logs: [...this.state.logs, ...logs], 
+        currentStep: {
+          ...this.state.currentStep,
+          [infra.kind] : validEvents[validEvents.length - 1]["created_resources"]
+        },
+      }, () => {
+        this.scrollToBottom(false)
+      })
+    }
+
+    ws.onerror = (err: ErrorEvent) => {
+      console.log('websocket err', err)
+    }
+
+    ws.onclose = () => {
+      console.log('closing provisioner websocket')
+    }
+
+    return ws
+  }
+
+  onEnd = () => {
+    let myInterval = setInterval(() => {
+      api.getClusters('<token>', {}, { 
+        id: this.context.currentProject.id 
+      }, (err: any, res: any) => {
+        if (err) {
+          console.log(err);
+        } else if (res.data) {
+          let clusters = res.data;
+          if (clusters.length > 0) {
+            this.props.history.push("dashboard");
+            clearInterval(myInterval);
+          }
+        }
+      });
+    }, 1000);
+  }
+
+  renderTabs = () => {
+    return this.state.infras.map((infra, i) => {
+      console.log(infra)
+      // return (
+      //   <ControllerTab 
+      //     key={i} 
+      //     selectedPod={this.state.selectedPod} 
+      //     selectPod={this.selectPod.bind(this)}
+      //     controller={c}
+      //     isLast={i === this.state.controllers.length - 1}
+      //     isFirst={i === 0}
+      //   />
+      // )
+    })
+  }
+
+  componentDidMount() {
+    let { currentProject } = this.context;
+
+    // Check if current project is provisioning
+    api.getInfra('<token>', {}, { 
+      project_id: currentProject.id 
+    }, (err: any, res: any) => {
+      if (err) return;
+      
+      let infras = res.data;
+      let error = false;
+      this.setState({ error, infras });
+    });
   }
 
   render() {
+    console.log(this.state.infras)
     return (
       <StyledProvisioner>
+        {this.renderTabs()}
         [TODO: implement provisioner]
       </StyledProvisioner>
     );
   }
 }
 
+Provisioner.contextType = Context;
+
+export default withRouter(Provisioner);
+
+
 const StyledProvisioner = styled.div`
   width: 100%;
   height: 350px;