Răsfoiți Sursa

Merge branch 'staging' of https://github.com/porter-dev/porter into beta.3.provisioning-integration

mergin
Alexander Belanger 5 ani în urmă
părinte
comite
68a8e0d6a3

+ 1 - 1
dashboard/src/components/SaveButton.tsx

@@ -86,7 +86,7 @@ const StatusWrapper = styled.div`
 
   > i {
     font-size: 18px;
-    margin-right: 5px;
+    margin-right: 10px;
     color: ${(props: { successful: boolean }) => props.successful ? '#4797ff' : '#fcba03'};
   }
 

+ 2 - 1
dashboard/src/main/home/Home.tsx

@@ -13,6 +13,7 @@ import Loading from '../../components/Loading';
 import Templates from './templates/Templates';
 import Integrations from "./integrations/Integrations";
 import UpdateProjectModal from './modals/UpdateProjectModal';
+import UpdateClusterModal from './modals/UpdateClusterModal';
 import ClusterInstructionsModal from './modals/ClusterInstructionsModal';
 import IntegrationsModal from './modals/IntegrationsModal';
 import IntegrationsInstructionsModal from './modals/IntegrationsInstructionsModal';
@@ -67,7 +68,7 @@ export default class Home extends Component<PropsType, StateType> {
                   viewData.push({
                     infra_id: el.id,
                     kind: el.kind,
-                  })
+                  });
                 }
               });
 

+ 188 - 0
dashboard/src/main/home/modals/UpdateClusterModal.tsx

@@ -0,0 +1,188 @@
+import React, { Component } from 'react';
+import styled from 'styled-components';
+import close from '../../../assets/close.png';
+import gradient from '../../../assets/gradient.jpg';
+
+import api from '../../../shared/api';
+import { Context } from '../../../shared/Context';
+
+import SaveButton from '../../../components/SaveButton';
+import InputRow from '../../../components/values-form/InputRow';
+import ConfirmOverlay from '../../../components/ConfirmOverlay';
+
+type PropsType = {
+};
+
+type StateType = {
+  clusterName: string,
+  status: string | null,
+  showDeleteOverlay: boolean
+};
+
+export default class UpdateClusterModal extends Component<PropsType, StateType> {
+  state = {
+    clusterName: this.context.currentCluster.name,
+    status: null as string | null,
+    showDeleteOverlay: false,
+  };
+  
+  handleDelete = () => {
+    let { currentProject, currentCluster } = this.context;
+    this.setState({ status: 'loading' });
+    api.deleteCluster('<token>', {}, { 
+      project_id: currentProject.id,
+      cluster_id: currentCluster.id,
+    }, (err: any, res: any) => {
+      if (err) {
+        this.setState({ status: 'error' });
+        // console.log(err)
+      } else {
+        alert('nice');
+        this.setState({ status: 'successful', showDeleteOverlay: false });
+      }
+    });
+  }
+
+  render() {
+    return (
+      <StyledUpdateProjectModal>
+        <CloseButton onClick={() => {
+          this.context.setCurrentModal(null, null);
+        }}>
+          <CloseButtonImg src={close} />
+        </CloseButton>
+
+        <ModalTitle>Cluster Settings</ModalTitle>
+        <Subtitle>
+          Cluster name
+        </Subtitle>
+
+        <InputWrapper>
+          <ProjectIcon>
+            <ProjectImage src={gradient} />
+            <Letter>{this.state.clusterName ? this.state.clusterName[0].toUpperCase() : '-'}</Letter>
+          </ProjectIcon>
+          <InputRow
+            disabled={true}
+            type='string'
+            value={this.state.clusterName}
+            setValue={(x: string) => this.setState({ clusterName: x })}
+            placeholder='ex: perspective-vortex'
+            width='470px'
+          />
+        </InputWrapper>
+
+        <SaveButton
+          text='Delete Cluster'
+          color='#b91133'
+          onClick={() => this.setState({ showDeleteOverlay: true })}
+          status={this.state.status}
+        />
+
+        <ConfirmOverlay
+          show={this.state.showDeleteOverlay}
+          message={`Are you sure you want to delete ${this.state.clusterName}?`}
+          onYes={this.handleDelete}
+          onNo={() => this.setState({ showDeleteOverlay: false })}
+        />
+      </StyledUpdateProjectModal>
+      );
+  }
+}
+
+UpdateClusterModal.contextType = Context;
+
+const Letter = styled.div`
+  height: 100%;
+  width: 100%;
+  position: absolute;
+  background: #00000028;
+  top: 0;
+  left: 0;
+  display: flex;
+  color: white;
+  align-items: center;
+  justify-content: center;
+`;
+
+const ProjectImage = styled.img`
+  width: 100%;
+  height: 100%;
+`;
+
+const ProjectIcon = styled.div`
+  width: 25px;
+  min-width: 25px;
+  height: 25px;
+  border-radius: 3px;
+  overflow: hidden;
+  position: relative;
+  margin-right: 10px;
+  font-weight: 400;
+  margin-top: 14px;
+`;
+
+const InputWrapper = styled.div`
+  display: flex;
+  align-items: center;
+`;
+
+const Subtitle = styled.div`
+  margin-top: 23px;
+  font-family: 'Work Sans', sans-serif;
+  font-size: 13px;
+  color: #aaaabb;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  margin-bottom: -10px;
+`;
+
+const ModalTitle = styled.div`
+  margin: 0px 0px 13px;
+  display: flex;
+  flex: 1;
+  font-family: 'Assistant';
+  font-size: 18px;
+  color: #ffffff;
+  user-select: none;
+  font-weight: 700;
+  align-items: center;
+  position: relative;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+`;
+
+const CloseButton = styled.div`
+  position: absolute;
+  display: block;
+  width: 40px;
+  height: 40px;
+  padding: 13px 0 12px 0;
+  z-index: 1;
+  text-align: center;
+  border-radius: 50%;
+  right: 15px;
+  top: 12px;
+  cursor: pointer;
+  :hover {
+    background-color: #ffffff11;
+  }
+`;
+
+const CloseButtonImg = styled.img`
+  width: 14px;
+  margin: 0 auto;
+`;
+
+const StyledUpdateProjectModal= styled.div`
+  width: 100%;
+  position: absolute;
+  left: 0;
+  top: 0;
+  height: 100%;
+  padding: 25px 32px;
+  overflow: hidden;
+  border-radius: 6px;
+  background: #202227;
+`;

+ 13 - 3
dashboard/src/main/home/new-project/NewProject.tsx

@@ -211,7 +211,12 @@ export default class NewProject extends Component<PropsType, StateType> {
         ecr_name: `${proj.name}-registry`
       }, {id: proj.id}, (err: any, ecr:any) => {
         if (err) {
-          console.log(err)
+          this.setState({ 
+            status: 'Please provide valid AWS credentials.',
+            awsRegion: '',
+            awsAccessId: '',
+            awsSecretKey: '', 
+          });
           return;
         }
 
@@ -232,7 +237,7 @@ export default class NewProject extends Component<PropsType, StateType> {
       aws_cluster_id: clusterName,
     }, { id: proj.id }, (err: any, res: any) => {
       if (err) {
-        console.log(err)
+        console.log(err);
         return;
       }
 
@@ -241,7 +246,12 @@ export default class NewProject extends Component<PropsType, StateType> {
         eks_name: clusterName,
       }, { id: proj.id}, (err: any, eks: any) => {
         if (err) {
-          console.log(err)
+          this.setState({ 
+            status: 'Please provide valid AWS credentials.',
+            awsRegion: '',
+            awsAccessId: '',
+            awsSecretKey: '', 
+          });
           return;
         }
 

+ 4 - 5
dashboard/src/main/home/new-project/Provisioner.tsx

@@ -37,9 +37,9 @@ export default class Provisioner extends Component<PropsType, StateType> {
 
   isJSON = (str: string) => {
     try {
-        JSON.parse(str);
+      JSON.parse(str);
     } catch (e) {
-        return false;
+      return false;
     }
     return true;
   }
@@ -49,8 +49,6 @@ export default class Provisioner extends Component<PropsType, StateType> {
     let protocol = process.env.NODE_ENV == 'production' ? 'wss' : 'ws'
     let viewData = this.props.viewData || []
 
-    console.log("viewData", viewData)
-
     let websockets = viewData.map((infra: any) => {
       let ws = new WebSocket(`${protocol}://${process.env.API_SERVER}/api/projects/${currentProject.id}/provision/${infra.kind}/${infra.infra_id}/logs`)
       
@@ -166,7 +164,8 @@ export default class Provisioner extends Component<PropsType, StateType> {
       currentStep += this.state.currentStep[key]
     }
 
-    if (currentStep === maxStep) {
+    if (maxStep !== 0 && currentStep === maxStep) {
+      console.log('Provisioning complete.')
       this.props.setCurrentView('dashboard');
     }
 

+ 7 - 4
dashboard/src/main/home/sidebar/ProjectSection.tsx

@@ -28,17 +28,20 @@ export default class ProjectSection extends Component<PropsType, StateType> {
       if (err) {
         console.log(err);
       } else if (res.data) {
-        let anyProvisioning = false;
+
+        let viewData = [] as any[]
         res.data.forEach((el: InfraType) => {
           if (el.status === 'creating') {
-            anyProvisioning = true;
-            this.props.setCurrentView('provisioner', {
+            viewData.push({
               infra_id: el.id,
               kind: el.kind,
             });
           }
         });
-        if (!anyProvisioning) {
+
+        if (viewData.length > 0) {
+          this.props.setCurrentView('provisioner', viewData);
+        } else {
           this.props.setCurrentView('dashboard');
         }
       }

+ 18 - 0
dashboard/src/shared/api.tsx

@@ -276,8 +276,26 @@ const getInfra = baseApi<{
   return `/api/projects/${pathParams.project_id}/infra`;
 });
 
+const destroyCluster = baseApi<{
+}, {
+  project_id: number,
+  infra_id: number,
+}>('POST', pathParams => {
+  return `/projects/${pathParams.project_id}/infra/${pathParams.infra_id}/eks/destroy`;
+});
+
+const deleteCluster = baseApi<{
+}, {
+  project_id: number,
+  cluster_id: number,
+}>('DELETE', pathParams => {
+  return `/projects/${pathParams.project_id}/clusters/${pathParams.cluster_id}`;
+})
+
 // Bundle export to allow default api import (api.<method> is more readable)
 export default {
+  deleteCluster,
+  destroyCluster,
   getInfra,
   linkGithubProject,
   getGitRepos,

+ 3 - 2
go.mod

@@ -1,6 +1,6 @@
 module github.com/porter-dev/porter
 
-go 1.14
+go 1.15
 
 require (
 	cloud.google.com/go v0.65.0
@@ -12,6 +12,7 @@ require (
 	github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20201113001948-d77edb6d2e47
 	github.com/containerd/containerd v1.4.1 // indirect
 	github.com/coreos/rkt v1.30.0
+	github.com/creack/pty v1.1.11 // indirect
 	github.com/docker/cli v0.0.0-20200130152716-5d0cf8839492
 	github.com/docker/docker v1.4.2-0.20200203170920-46ec8731fbce
 	github.com/docker/docker-credential-helpers v0.6.3
@@ -57,7 +58,7 @@ require (
 	golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0
 	golang.org/x/exp v0.0.0-20200908183739-ae8ad444f925 // indirect
 	golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43
-	golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6 // indirect
+	golang.org/x/sys v0.0.0-20210108172913-0df2131ae363 // indirect
 	golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect
 	google.golang.org/api v0.30.0
 	google.golang.org/genproto v0.0.0-20201014134559-03b6142f0dc9

+ 5 - 2
go.sum

@@ -206,6 +206,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma
 github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
+github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg=
 github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
 github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -668,8 +670,7 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
 github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
-github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
+github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI=
 github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -1222,6 +1223,8 @@ golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6 h1:DvY3Zkh7KabQE/kfzMvYvKirS
 golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210108172913-0df2131ae363 h1:wHn06sgWHMO1VsQ8F+KzDJx/JzqfsNLnc+oEi07qD7s=
+golang.org/x/sys v0.0.0-20210108172913-0df2131ae363/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=