Browse Source

delete chart frontend

jusrhee 5 năm trước cách đây
mục cha
commit
c4f044b946

+ 37 - 5
dashboard/src/main/home/cluster-dashboard/expanded-chart/ExpandedChart.tsx

@@ -18,7 +18,7 @@ import StatusSection from './status/StatusSection';
 import ValuesWrapper from '../../../../components/values-form/ValuesWrapper';
 import ValuesForm from '../../../../components/values-form/ValuesForm';
 import SettingsSection from './SettingsSection';
-import { format } from 'util';
+import ConfirmOverlay from '../../../../components/ConfirmOverlay';
 
 type PropsType = {
   namespace: string,
@@ -44,6 +44,7 @@ type StateType = {
   controllers: Record<string, Record<string, any>>,
   websockets: Record<string, any>,
   url: string | null,
+  showDeleteOverlay: boolean,
 };
 
 export default class ExpandedChart extends Component<PropsType, StateType> {
@@ -62,6 +63,7 @@ export default class ExpandedChart extends Component<PropsType, StateType> {
     controllers: {} as Record<string, Record<string, any>>,
     websockets : {} as Record<string, any>,
     url: null as string | null,
+    showDeleteOverlay: false,
   }
 
   // Retrieve full chart data (includes form and values)
@@ -250,6 +252,7 @@ export default class ExpandedChart extends Component<PropsType, StateType> {
             currentChart={chart}
             refreshChart={this.refreshChart}
             setCurrentView={setCurrentView}
+            setShowDeleteOverlay={(x: boolean) => this.setState({ showDeleteOverlay: x })}
           /> 
         );
       case 'graph': 
@@ -333,7 +336,6 @@ export default class ExpandedChart extends Component<PropsType, StateType> {
     // Append universal tabs
     tabOptions.push(
       { label: 'Status', value: 'status' },
-      { label: 'Deploy', value: 'settings' },
       { label: 'Chart Overview', value: 'graph' },
     );
 
@@ -344,6 +346,9 @@ export default class ExpandedChart extends Component<PropsType, StateType> {
       );
     }
 
+    // Settings tab is always last
+    tabOptions.push({ label: 'Settings', value: 'settings' });
+
     // Filter tabs if previewing an old revision
     if (this.state.isPreview) {
       let liveTabs = ['status', 'settings', 'deploy'];
@@ -518,15 +523,42 @@ export default class ExpandedChart extends Component<PropsType, StateType> {
     }
   }
 
+  handleUninstallChart = () => {
+    let { currentProject, currentCluster } = this.context;
+    let { currentChart } = this.props;
+    console.log('here', currentChart.namespace, StorageType.Secret)
+    api.uninstallTemplate('<token>', {
+      namespace: currentChart.namespace,
+      cluster_id: currentCluster.id,
+      storage: StorageType.Secret,
+    }, {
+      name: currentChart.name,
+      id: currentProject.id,
+      cluster_id: currentCluster.id,
+    }, (err: any, res: any) => {
+      if (err) {
+        console.log(err)
+      } else {
+        console.log('worked i guess');
+      }
+    });
+  }
+
   render() {
     let { currentChart, setCurrentChart } = this.props;
     let chart = currentChart;
     let status = this.getChartStatus(chart.info.status);
 
     return ( 
-      <div>
-        <CloseOverlay onClick={() => setCurrentChart(null)}/>
+      <>
+        <CloseOverlay onClick={() => setCurrentChart(null)} />
         <StyledExpandedChart>
+          <ConfirmOverlay
+            show={this.state.showDeleteOverlay}
+            message={`Are you sure you want to delete ${currentChart.name}?`}
+            onYes={this.handleUninstallChart}
+            onNo={() => this.setState({ showDeleteOverlay: false })}
+          />
           <HeaderWrapper>
             <TitleSection>
               <Title>
@@ -580,7 +612,7 @@ export default class ExpandedChart extends Component<PropsType, StateType> {
             {this.renderTabContents()}
           </TabRegion>
         </StyledExpandedChart>
-      </div>
+      </>
     );
   }
 }

+ 29 - 2
dashboard/src/main/home/cluster-dashboard/expanded-chart/SettingsSection.tsx

@@ -17,6 +17,7 @@ type PropsType = {
   currentChart: ChartType,
   refreshChart: () => void,
   setCurrentView: (x: string) => void,
+  setShowDeleteOverlay: (x: boolean) => void,
 };
 
 type StateType = {
@@ -156,7 +157,7 @@ export default class SettingsSection extends Component<PropsType, StateType> {
   }
 
   renderWebhookSection = () => {
-    if (this.state.webhookToken) {
+    if (true || this.state.webhookToken) {
       let webhookText = `curl -X POST 'https://dashboard.getporter.dev/api/webhooks/deploy/${this.state.webhookToken}?commit=???&repository=???'`;
       return (
         <>
@@ -184,9 +185,13 @@ export default class SettingsSection extends Component<PropsType, StateType> {
     return (
       <Wrapper>
         <StyledSettingsSection>
-          <Heading>Connected source</Heading>
+          <Heading>Connected Source</Heading>
           {this.renderSourceSection()}
           {this.renderWebhookSection()}
+          <Heading>Additional Settings</Heading>
+          <Button color='#b91133' onClick={() => this.props.setShowDeleteOverlay(true)}>
+            Delete {this.props.currentChart.name}
+          </Button>
         </StyledSettingsSection>
         <SaveButton
           text='Save Settings'
@@ -202,6 +207,27 @@ export default class SettingsSection extends Component<PropsType, StateType> {
 
 SettingsSection.contextType = Context;
 
+const Button = styled.button`
+  height: 40px;
+  font-size: 13px;
+  margin-top: 20px;
+  font-weight: 500;
+  font-family: 'Work Sans', sans-serif;
+  color: white;
+  padding: 6px 20px 7px 20px;
+  text-align: left;
+  border: 0;
+  border-radius: 5px;
+  background: ${(props) => (!props.disabled ? props.color : '#aaaabb')};
+  box-shadow: ${(props) => (!props.disabled ? '0 2px 5px 0 #00000030' : 'none')};
+  cursor: ${(props) => (!props.disabled ? 'pointer' : 'default')};
+  user-select: none;
+  :focus { outline: 0 }
+  :hover {
+    filter: ${(props) => (!props.disabled ? 'brightness(120%)' : '')};
+  }
+`;
+
 const Webhook = styled.div`
   width: 100%;
   border: 1px solid #ffffff55;
@@ -262,6 +288,7 @@ const StyledSettingsSection = styled.div`
   height: calc(100% - 60px);
   background: #ffffff11;
   padding: 0 35px;
+  padding-bottom: 50px;
   position: relative;
   border-radius: 5px;
   overflow: auto;

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

@@ -190,6 +190,18 @@ const deployTemplate = baseApi<{
   return `/api/projects/${id}/deploy/${name}/${version}?cluster_id=${cluster_id}`;
 });
 
+const uninstallTemplate = baseApi<{
+  namespace: string,
+  cluster_id: number,
+  storage: StorageType,
+}, {
+  id: number,
+  name: string, 
+  cluster_id: number,
+}>('POST', pathParams => {
+  return `/api/projects/${pathParams.id}/deploy/${pathParams.name}?cluster_id=${pathParams.cluster_id}`;
+});
+
 const getClusterIntegrations = baseApi('GET', '/api/integrations/cluster');
 
 const getRegistryIntegrations = baseApi('GET', '/api/integrations/registry');
@@ -322,6 +334,7 @@ const createGKE = baseApi<{
 
 // Bundle export to allow default api import (api.<method> is more readable)
 export default {
+  uninstallTemplate,
   createGCR,
   createGKE,
   createGCPIntegration,

+ 3 - 0
go.sum

@@ -1452,8 +1452,11 @@ gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
 gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
 gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
 gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
+helm.sh/helm v1.2.1 h1:Jrn7kKQqQ/hnFWZEX+9pMFvYqFexkzrBnGqYBmIph7c=
+helm.sh/helm v2.17.0+incompatible h1:cSe3FaQOpRWLDXvTObQNj0P7WI98IG5yloU6tQVls2k=
 helm.sh/helm/v3 v3.3.4 h1:tbad6WQVMxEw1HlVBvI2rQqOblmI5lgXOrWAMwJ198M=
 helm.sh/helm/v3 v3.3.4/go.mod h1:CyCGQa53/k1JFxXvXveGwtfJ4cuB9zkaBSGa5rnAiHU=
+helm.sh/helm/v3 v3.5.0 h1:uqIT3Bh4hVEyZRThyTPik8FkiABj3VJIY+POvDFT3a4=
 honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

+ 8 - 0
internal/helm/agent.go

@@ -142,6 +142,14 @@ func (a *Agent) InstallChart(
 	return cmd.Run(conf.Chart, conf.Values)
 }
 
+// UninstallChart uninstalls a chart
+func (a *Agent) UninstallChart(
+	name string,
+) (*release.UninstallReleaseResponse, error) {
+	cmd := action.NewUninstall(a.ActionConfig)
+	return cmd.Run(name)
+}
+
 // RollbackRelease rolls a release back to a specified revision/version
 func (a *Agent) RollbackRelease(
 	name string,

+ 38 - 0
server/api/deploy_handler.go

@@ -2,6 +2,7 @@ package api
 
 import (
 	"encoding/json"
+	"fmt"
 	"math/rand"
 	"net/http"
 	"net/url"
@@ -121,3 +122,40 @@ func (app *App) HandleDeployTemplate(w http.ResponseWriter, r *http.Request) {
 
 	w.WriteHeader(http.StatusOK)
 }
+
+// HandleUninstallTemplate triggers a chart deployment from a template
+func (app *App) HandleUninstallTemplate(w http.ResponseWriter, r *http.Request) {
+	name := chi.URLParam(r, "name")
+	fmt.Println(name)
+
+	form := &forms.GetReleaseForm{
+		ReleaseForm: &forms.ReleaseForm{
+			Form: &helm.Form{
+				Repo: app.Repo,
+			},
+		},
+		Name:     name,
+		Revision: int(0),
+	}
+
+	agent, err := app.getAgentFromQueryParams(
+		w,
+		r,
+		form.ReleaseForm,
+		form.ReleaseForm.PopulateHelmOptionsFromQueryParams,
+	)
+
+	// errors are handled in app.getAgentFromQueryParams
+	if err != nil {
+		fmt.Println("asdf")
+		return
+	}
+
+	_, err = agent.UninstallChart(name)
+	if err != nil {
+		fmt.Println("gg")
+	}
+
+	w.WriteHeader(http.StatusOK)
+	return
+}

+ 15 - 0
server/router/router.go

@@ -765,6 +765,21 @@ func New(a *api.App) *chi.Mux {
 			),
 		)
 
+		// /api/projects/{project_id}/deploy routes
+		r.Method(
+			"POST",
+			"/projects/{project_id}/deploy/{name}",
+			auth.DoesUserHaveProjectAccess(
+				auth.DoesUserHaveClusterAccess(
+					requestlog.NewHandler(a.HandleUninstallTemplate, l),
+					mw.URLParam,
+					mw.QueryParam,
+				),
+				mw.URLParam,
+				mw.ReadAccess,
+			),
+		)
+
 		// /api/projects/{project_id}/k8s routes
 		r.Method(
 			"GET",