Selaa lähdekoodia

deletion without namespace cleanup

Justin Rhee 3 vuotta sitten
vanhempi
sitoutus
c0ce12945f

+ 66 - 0
api/server/handlers/stacks/delete_porter_app.go

@@ -0,0 +1,66 @@
+package stacks
+
+import (
+	"net/http"
+
+	"github.com/porter-dev/porter/api/server/authz"
+	"github.com/porter-dev/porter/api/server/handlers"
+	"github.com/porter-dev/porter/api/server/shared"
+	"github.com/porter-dev/porter/api/server/shared/apierrors"
+	"github.com/porter-dev/porter/api/server/shared/config"
+	"github.com/porter-dev/porter/api/server/shared/requestutils"
+	"github.com/porter-dev/porter/api/types"
+	"github.com/porter-dev/porter/internal/models"
+)
+
+type DeletePorterAppByNameHandler struct {
+	handlers.PorterHandlerReadWriter
+	authz.KubernetesAgentGetter
+}
+
+func NewDeletePorterAppByNameHandler(
+	config *config.Config,
+	decoderValidator shared.RequestDecoderValidator,
+	writer shared.ResultWriter,
+) *DeletePorterAppByNameHandler {
+	return &DeletePorterAppByNameHandler{
+		PorterHandlerReadWriter: handlers.NewDefaultPorterHandler(config, decoderValidator, writer),
+		KubernetesAgentGetter:   authz.NewOutOfClusterAgentGetter(config),
+	}
+}
+
+func (c *DeletePorterAppByNameHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	ctx := r.Context()
+	cluster, _ := ctx.Value(types.ClusterScope).(*models.Cluster)
+
+	name, reqErr := requestutils.GetURLParamString(r, types.URLParamReleaseName)
+	if reqErr != nil {
+		c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(reqErr, http.StatusBadRequest))
+		return
+	}
+
+	agent, agentErr := c.GetAgent(r, cluster, "")
+	if agentErr != nil {
+		c.HandleAPIError(w, r, apierrors.NewErrInternal(agentErr))
+		return
+	}
+
+	if err := agent.DeleteNamespace("porter–stack–" + name); err != nil {
+		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+		return
+	}
+
+	porterApp, appErr := c.Repo().PorterApp().ReadPorterAppByName(cluster.ID, name)
+	if appErr != nil {
+		c.HandleAPIError(w, r, apierrors.NewErrInternal(appErr))
+		return
+	}
+
+	delApp, delErr := c.Repo().PorterApp().DeletePorterApp(porterApp)
+	if delErr != nil {
+		c.HandleAPIError(w, r, apierrors.NewErrInternal(delErr))
+		return
+	}
+
+	c.WriteResult(w, r, delApp)
+}

+ 30 - 1
api/server/router/stack.go

@@ -83,7 +83,7 @@ func getStackRoutes(
 		Router:   r,
 	})
 
-	// GET /api/projects/{project_id}/clusters/{cluster_id}/stacks -> stacks.NewPorterAppListHandler
+	// GET /api/projects/{project_id}/clusters/{cluster_id}/stacks/{name} -> stacks.NewPorterAppListHandler
 	listPorterAppEndpoint := factory.NewAPIEndpoint(
 		&types.APIRequestMetadata{
 			Verb:   types.APIVerbList,
@@ -111,6 +111,35 @@ func getStackRoutes(
 		Router:   r,
 	})
 
+	// DELETE /api/projects/{project_id}/clusters/{cluster_id}/stacks -> release.NewDeletePorterAppByNameHandler
+	deletePorterAppByNameEndpoint := factory.NewAPIEndpoint(
+		&types.APIRequestMetadata{
+			Verb:   types.APIVerbDelete,
+			Method: types.HTTPVerbDelete,
+			Path: &types.Path{
+				Parent:       basePath,
+				RelativePath: relPath + "/{name}",
+			},
+			Scopes: []types.PermissionScope{
+				types.UserScope,
+				types.ProjectScope,
+				types.ClusterScope,
+			},
+		},
+	)
+
+	deletePorterAppByNameHandler := stacks.NewDeletePorterAppByNameHandler(
+		config,
+		factory.GetDecoderValidator(),
+		factory.GetResultWriter(),
+	)
+
+	routes = append(routes, &router.Route{
+		Endpoint: deletePorterAppByNameEndpoint,
+		Handler:  deletePorterAppByNameHandler,
+		Router:   r,
+	})
+
 	// POST /api/projects/{project_id}/clusters/{cluster_id}/stacks/update_config -> stacks.NewCreatePorterAppHandler
 	createPorterAppEndpoint := factory.NewAPIEndpoint(
 		&types.APIRequestMetadata{

+ 24 - 1
dashboard/src/main/home/app-dashboard/expanded-app/ExpandedApp.tsx

@@ -96,6 +96,27 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
     }
   };
 
+  const deletePorterApp = async () => {
+    setIsLoading(true);
+    const { appName } = props.match.params as any;
+    try {
+      const res = await api.deletePorterApp(
+        "<token>",
+        {},
+        {
+          cluster_id: currentCluster.id,
+          project_id: currentProject.id,
+          name: appName,
+        }
+      );
+      console.log(res);
+      setIsLoading(false);
+    } catch (err) {
+      setError(err);
+      setIsLoading(false);
+    }
+  }
+
   const renderIcon = (b: string, size?: string) => {
     var src = box;
     if (b) {
@@ -189,6 +210,7 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
     // setIsPreview(!isCurrent);
     getChartData(chart);
   };
+
   const appUpgradeVersion = useCallback(
     async (version: string, cb: () => void) => {
       // convert current values to yaml
@@ -261,6 +283,7 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
     });
     return `${time} on ${date}`;
   };
+  
   const renderTabContents = () => {
     switch (tab) {
       case "overview":
@@ -397,7 +420,7 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
         <ConfirmOverlay
           message={`Are you sure you want to delete "${appData.app.name}"?`}
           onYes={() => {
-            // deleteApp();
+            deletePorterApp();
           }}
           onNo={() => {
             setShowDeleteOverlay(false);

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

@@ -228,6 +228,18 @@ const updatePorterApp = baseApi<
   return `/api/projects/${project_id}/clusters/${cluster_id}/stacks/${name}`;
 });
 
+const deletePorterApp = baseApi<
+  {},
+  {
+    project_id: number;
+    cluster_id: number;
+    name: string;
+  }
+>("DELETE", (pathParams) => {
+  let { project_id, cluster_id, name } = pathParams;
+  return `/api/projects/${project_id}/clusters/${cluster_id}/stacks/${name}`;
+});
+
 const updatePorterStack = baseApi<
   {
     stack_name: string;
@@ -2566,6 +2578,7 @@ export default {
   getPorterApp,
   createPorterApp,
   updatePorterApp,
+  deletePorterApp,
   updatePorterStack,
   createConfigMap,
   deleteCluster,

+ 8 - 0
internal/repository/gorm/porter_app.go

@@ -51,3 +51,11 @@ func (repo *PorterAppRepository) UpdatePorterApp(app *models.PorterApp) (*models
 
 	return app, nil
 }
+
+func (repo *PorterAppRepository) DeletePorterApp(app *models.PorterApp) (*models.PorterApp, error) {
+	if err := repo.db.Delete(&app).Error; err != nil {
+		return nil, err
+	}
+
+	return app, nil
+}

+ 1 - 0
internal/repository/porter_app.go

@@ -10,4 +10,5 @@ type PorterAppRepository interface {
 	CreatePorterApp(app *models.PorterApp) (*models.PorterApp, error)
 	ListPorterAppByClusterID(clusterID uint) ([]*models.PorterApp, error)
 	UpdatePorterApp(app *models.PorterApp) (*models.PorterApp, error)
+	DeletePorterApp(app *models.PorterApp) (*models.PorterApp, error)
 }

+ 4 - 0
internal/repository/test/porter_app.go

@@ -33,3 +33,7 @@ func (repo *PorterAppRepository) UpdatePorterApp(app *models.PorterApp) (*models
 func (repo *PorterAppRepository) ListPorterAppByClusterID(clusterID uint) ([]*models.PorterApp, error) {
 	return nil, errors.New("cannot write database")
 }
+
+func (repo *PorterAppRepository) DeletePorterApp(app *models.PorterApp) (*models.PorterApp, error) {
+	return nil, errors.New("cannot write database")
+}