Prechádzať zdrojové kódy

cluster and project deletion across cloud providers. Fixes #249

sunguroku 5 rokov pred
rodič
commit
baad23f31d

+ 48 - 14
dashboard/src/main/home/Home.tsx

@@ -70,13 +70,14 @@ export default class Home extends Component<PropsType, StateType> {
       }
 
       if (res.data.length > 0 && (!currentCluster && !includesCompletedInfraSet(res.data))) {
-        // force refresh if currentView is already set to provisioner.
+        // force refresh if currentView is identical set to provisioner. Tentative solution before refactoring.
         this.setState({ currentView: 'dashboard'}, () => {
           this.setState({ currentView: 'provisioner', sidebarReady: true, });
         });
       } else {
-        // console.log('getting here', currentCluster)
-        this.setState({ currentView: 'dashboard', sidebarReady: true });
+        this.setState({ currentView: 'provisioner'}, () => {
+          this.setState({ currentView: 'dashboard', sidebarReady: true });
+        })
       }
     });
   }
@@ -357,7 +358,7 @@ export default class Home extends Component<PropsType, StateType> {
     let { setCurrentModal, currentProject } = this.context;
     api.deleteProject('<token>', {}, { id: currentProject.id }, (err: any, res: any) => {
       if (err) {
-        // console.log(err)
+        console.log(err)
       } else {
         this.projectOverlayCall();
       }
@@ -365,15 +366,21 @@ export default class Home extends Component<PropsType, StateType> {
 
     // Loop through and delete infra of all clusters we've provisioned
     api.getClusters('<token>', {}, { id: currentProject.id }, (err: any, res: any) => {
-      if (err) {
-        console.log(err);
-      } else {
-        res.data.forEach((cluster: ClusterType) => {
 
-          // Handle destroying infra we've provisioned
-          if (cluster.infra_id) {
-            console.log('destroying provisioned infra...', cluster.infra_id);
-            api.destroyCluster('<token>', { eks_name: cluster.name }, { 
+      if (err) { 
+        console.log(err); 
+        return; 
+      }
+      
+      for (var i = 0; i < res.data.length; i++) {
+        let cluster = res.data[i];
+        if (!cluster.infra_id) continue;
+
+        // Handle destroying infra we've provisioned
+        switch (cluster.service) {
+
+          case "eks":
+            api.destroyEKS('<token>', { eks_name: cluster.name }, { 
               project_id: currentProject.id,
               infra_id: cluster.infra_id,
             }, (err: any, res: any) => {
@@ -383,8 +390,34 @@ export default class Home extends Component<PropsType, StateType> {
                 console.log('destroyed provisioned infra:', cluster.infra_id);
               }
             });
-          }
-        });
+            break;
+
+          case 'gke':
+            api.destroyGKE('<token>', { gke_name: cluster.name }, { 
+              project_id: currentProject.id,
+              infra_id: cluster.infra_id,
+            }, (err: any, res: any) => {
+              if (err) {
+                console.log(err)
+              } else {
+                console.log('destroyed provisioned infra.');
+              }
+            });
+            break;
+
+          case 'doks':
+            api.destroyDOKS('<token>', { doks_name: cluster.name }, { 
+              project_id: currentProject.id,
+              infra_id: cluster.infra_id,
+            }, (err: any, res: any) => {
+              if (err) {
+                console.log(err)
+              } else {
+                console.log('destroyed provisioned infra.');
+              }
+            });
+            break;
+        }
       }
     });
     setCurrentModal(null, null)
@@ -393,6 +426,7 @@ export default class Home extends Component<PropsType, StateType> {
 
   render() {
     let { currentModal, setCurrentModal, currentProject } = this.context;
+
     return (
       <StyledHome>
         {currentModal === 'ClusterInstructionsModal' &&

+ 60 - 12
dashboard/src/main/home/modals/UpdateClusterModal.tsx

@@ -35,15 +35,33 @@ export default class UpdateClusterModal extends Component<PropsType, StateType>
       project_id: currentProject.id,
       cluster_id: currentCluster.id,
     }, (err: any, res: any) => {
+
       if (err) {
         this.setState({ status: 'error' });
         console.log(err)
-      } else {
+        return;
+      }
+
+      if (!currentCluster?.infra_id) return;
+
+      // Handle destroying infra we've provisioned
+      switch (currentCluster.service) {
+        case 'eks':
+          api.destroyEKS('<token>', { eks_name: currentCluster.name }, { 
+            project_id: currentProject.id,
+            infra_id: currentCluster.infra_id,
+          }, (err: any, res: any) => {
+            if (err) {
+              this.setState({ status: 'error' });
+              console.log(err)
+            } else {
+              console.log('destroyed provisioned infra.');
+            }
+          });
+          break;
 
-        // Handle destroying infra we've provisioned
-        if (currentCluster.infra_id) {
-          console.log('destroying provisioned infra...');
-          api.destroyCluster('<token>', { eks_name: currentCluster.name }, { 
+        case 'gke':
+          api.destroyGKE('<token>', { gke_name: currentCluster.name }, { 
             project_id: currentProject.id,
             infra_id: currentCluster.infra_id,
           }, (err: any, res: any) => {
@@ -54,15 +72,46 @@ export default class UpdateClusterModal extends Component<PropsType, StateType>
               console.log('destroyed provisioned infra.');
             }
           });
-        }
+          break;
 
-        this.props.setRefreshClusters(true);
-        this.setState({ status: 'successful', showDeleteOverlay: false });
-        this.context.setCurrentModal(null, null);
+        case 'doks':
+          api.destroyDOKS('<token>', { doks_name : currentCluster.name }, { 
+            project_id: currentProject.id,
+            infra_id: currentCluster.infra_id,
+          }, (err: any, res: any) => {
+            if (err) {
+              this.setState({ status: 'error' });
+              console.log(err)
+            } else {
+              console.log('destroyed provisioned infra.');
+            }
+          });
+          break;
       }
+        
+      this.props.setRefreshClusters(true);
+      this.setState({ status: 'successful', showDeleteOverlay: false });
+      this.context.setCurrentModal(null, null);
     });
   }
 
+  renderWarning = () => {
+    let { currentCluster } = this.context;
+    if (!currentCluster?.infra_id || !currentCluster.service) {
+      return(
+        <Warning highlight={true}>
+          ⚠️ Since this cluster was not provisioned by Porter, deleting the cluster will only detach this cluster from your project. To delete the cluster itself, you must do so manually.
+        </Warning>
+      )    
+    }
+
+    return(
+      <Warning highlight={true}>
+        ⚠️ Deletion may result in dangling resources. Please visit your cloud provider's console to ensure that all resources have been removed. Note that deleting the cluster does not delete your registries.
+      </Warning>
+    )    
+  }
+
   render() {
     return (
       <StyledUpdateProjectModal>
@@ -91,9 +140,8 @@ export default class UpdateClusterModal extends Component<PropsType, StateType>
           />
         </InputWrapper>
 
-        <Warning highlight={true}>
-          ⚠️ Deletion may result in dangling resources. Please visit the AWS console to ensure that all resources have been removed.
-        </Warning>
+        {this.renderWarning()}
+
         <Help 
           href='https://docs.getporter.dev/docs/getting-started-with-porter-on-aws#deleting-provisioned-resources'
           target='_blank'

+ 11 - 4
dashboard/src/main/home/project-settings/ProjectSettings.tsx

@@ -29,7 +29,7 @@ export default class ProjectSettings extends Component<PropsType, StateType> {
   }
 
   componentDidMount() {
-    let { currentProject, user } = this.context;
+    let { currentProject } = this.context;
     this.setState({ projectName: currentProject.name });
   }
 
@@ -40,7 +40,13 @@ export default class ProjectSettings extends Component<PropsType, StateType> {
       return (
         <>
           <Heading isAtTop={true}>Delete Project</Heading>
-          <Helper>Permanently delete this project. <Warning highlight={true}>This action cannot be undone.</Warning></Helper>
+          <Helper>
+            Permanently delete this project. This will destroy all clusters tied to this project that have been provisioned by Porter. Note that this will not delete the image registries provisioned by Porter. To delete the registries, please do so manually in your cloud console.
+          </Helper>
+
+          <Warning highlight={true}>This action cannot be undone.</Warning>
+
+
           <DeleteButton
             onClick={() => {
               this.context.setCurrentModal('UpdateProjectModal', {
@@ -76,9 +82,10 @@ export default class ProjectSettings extends Component<PropsType, StateType> {
 
 ProjectSettings.contextType = Context;
 
-const Warning = styled.span`
+const Warning = styled.div`
+  font-size: 13px;
   color: ${(props: { highlight: boolean, makeFlush?: boolean }) => props.highlight ? '#f5cb42' : ''};
-  margin-left: 5px;
+  margin-bottom: 20px;
 `;
 
 const Title = styled.div`

+ 0 - 1
dashboard/src/main/home/provisioner/ProvisionerStatus.tsx

@@ -70,7 +70,6 @@ export default class ProvisionerStatus extends Component<PropsType, StateType> {
       } 
       
       let infras = filterOldInfras(res.data);
-      console.log('infras: ', res.data);
       let error = false;
 
       let maxStep = {} as Record<string, number>

+ 11 - 0
dashboard/src/main/home/templates/expanded-template/LaunchTemplate.tsx

@@ -77,9 +77,20 @@ export default class LaunchTemplate extends Component<PropsType, StateType> {
     }, (err: any, res: any) => {
       if (err) {
         this.setState({ saveValuesStatus: 'error' });
+        posthog.capture('Failed to deploy template', {
+          name: this.props.currentTemplate.name,
+          namespace: this.state.selectedNamespace,
+          values: values,
+          error: err
+        })
       } else {
         // this.props.setCurrentView('cluster-dashboard');
         this.setState({ saveValuesStatus: 'successful' });
+        posthog.capture('Deployed template', {
+          name: this.props.currentTemplate.name,
+          namespace: this.state.selectedNamespace,
+          values: values,
+        })
       }
     });
   }

+ 22 - 2
dashboard/src/shared/api.tsx

@@ -296,7 +296,7 @@ const getInfra = baseApi<{
   return `/api/projects/${pathParams.project_id}/infra`;
 });
 
-const destroyCluster = baseApi<{
+const destroyEKS = baseApi<{
   eks_name: string,
 }, {
   project_id: number,
@@ -305,6 +305,24 @@ const destroyCluster = baseApi<{
   return `/api/projects/${pathParams.project_id}/infra/${pathParams.infra_id}/eks/destroy`;
 });
 
+const destroyGKE = baseApi<{
+  gke_name: string,
+}, {
+  project_id: number,
+  infra_id: number,
+}>('POST', pathParams => {
+  return `/api/projects/${pathParams.project_id}/infra/${pathParams.infra_id}/gke/destroy`;
+});
+
+const destroyDOKS = baseApi<{
+  doks_name: string,
+}, {
+  project_id: number,
+  infra_id: number,
+}>('POST', pathParams => {
+  return `/api/projects/${pathParams.project_id}/infra/${pathParams.infra_id}/doks/destroy`;
+});
+
 const deleteCluster = baseApi<{
 }, {
   project_id: number,
@@ -392,7 +410,9 @@ export default {
   deleteInvite,
   deleteProject,
   deployTemplate,
-  destroyCluster,
+  destroyEKS,
+  destroyGKE,
+  destroyDOKS,
   getBranchContents,
   getBranches,
   getChart,

+ 2 - 1
dashboard/src/shared/types.tsx

@@ -3,7 +3,8 @@ export interface ClusterType {
   name: string,
   server: string,
   service_account_id: number
-  infra_id?: number
+  infra_id?: number,
+  service?: string,
 }
 
 export interface ChartType {