ソースを参照

add delete job and stop job handlers

Alexander Belanger 4 年 前
コミット
b2279189b1

+ 46 - 0
api/server/handlers/jobs/delete.go

@@ -0,0 +1,46 @@
+package jobs
+
+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/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 DeleteHandler struct {
+	handlers.PorterHandlerReadWriter
+	authz.KubernetesAgentGetter
+}
+
+func NewDeleteHandler(
+	config *config.Config,
+) *DeleteHandler {
+	return &DeleteHandler{
+		PorterHandlerReadWriter: handlers.NewDefaultPorterHandler(config, nil, nil),
+		KubernetesAgentGetter:   authz.NewOutOfClusterAgentGetter(config),
+	}
+}
+
+func (c *DeleteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	cluster, _ := r.Context().Value(types.ClusterScope).(*models.Cluster)
+	agent, err := c.GetAgent(r, cluster)
+	name, _ := requestutils.GetURLParamString(r, types.URLParamJobName)
+	namespace, _ := requestutils.GetURLParamString(r, types.URLParamNamespace)
+
+	if err != nil {
+		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+		return
+	}
+
+	err = agent.DeleteJob(name, namespace)
+
+	if err != nil {
+		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+		return
+	}
+}

+ 50 - 0
api/server/handlers/jobs/get_pods.go

@@ -0,0 +1,50 @@
+package jobs
+
+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 GetPodsHandler struct {
+	handlers.PorterHandlerReadWriter
+	authz.KubernetesAgentGetter
+}
+
+func NewGetPodsHandler(
+	config *config.Config,
+	writer shared.ResultWriter,
+) *GetPodsHandler {
+	return &GetPodsHandler{
+		PorterHandlerReadWriter: handlers.NewDefaultPorterHandler(config, nil, writer),
+		KubernetesAgentGetter:   authz.NewOutOfClusterAgentGetter(config),
+	}
+}
+
+func (c *GetPodsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	cluster, _ := r.Context().Value(types.ClusterScope).(*models.Cluster)
+	agent, err := c.GetAgent(r, cluster)
+	name, _ := requestutils.GetURLParamString(r, types.URLParamJobName)
+	namespace, _ := requestutils.GetURLParamString(r, types.URLParamNamespace)
+
+	if err != nil {
+		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+		return
+	}
+
+	pods, err := agent.GetJobPods(namespace, name)
+
+	if err != nil {
+		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+		return
+	}
+
+	c.WriteResult(w, r, pods)
+}

+ 49 - 0
api/server/handlers/jobs/stop.go

@@ -0,0 +1,49 @@
+package jobs
+
+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/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 StopHandler struct {
+	handlers.PorterHandlerReadWriter
+	authz.KubernetesAgentGetter
+}
+
+func NewStopHandler(
+	config *config.Config,
+) *StopHandler {
+	return &StopHandler{
+		PorterHandlerReadWriter: handlers.NewDefaultPorterHandler(config, nil, nil),
+		KubernetesAgentGetter:   authz.NewOutOfClusterAgentGetter(config),
+	}
+}
+
+func (c *StopHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	cluster, _ := r.Context().Value(types.ClusterScope).(*models.Cluster)
+	agent, err := c.GetAgent(r, cluster)
+	name, _ := requestutils.GetURLParamString(r, types.URLParamJobName)
+	namespace, _ := requestutils.GetURLParamString(r, types.URLParamNamespace)
+
+	if err != nil {
+		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+		return
+	}
+
+	err = agent.StopJobWithJobSidecar(namespace, name)
+
+	if err != nil {
+		c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(
+			err,
+			http.StatusBadRequest,
+		))
+		return
+	}
+}

+ 98 - 0
api/server/router/namespace.go

@@ -5,6 +5,7 @@ import (
 
 	"github.com/go-chi/chi"
 
+	"github.com/porter-dev/porter/api/server/handlers/jobs"
 	"github.com/porter-dev/porter/api/server/handlers/namespace"
 	"github.com/porter-dev/porter/api/server/shared"
 	"github.com/porter-dev/porter/api/server/shared/config"
@@ -297,5 +298,102 @@ func getNamespaceRoutes(
 		Router:   r,
 	})
 
+	// GET /api/projects/{project_id}/clusters/{cluster_id}/namespaces/{namespace}/jobs/{name}/pods -> jobs.NewGetPodsHandler
+	getJobPodsEndpoint := factory.NewAPIEndpoint(
+		&types.APIRequestMetadata{
+			Verb:   types.APIVerbList,
+			Method: types.HTTPVerbGet,
+			Path: &types.Path{
+				Parent: basePath,
+				RelativePath: fmt.Sprintf(
+					"%s/jobs/{%s}/pods",
+					relPath,
+					types.URLParamJobName,
+				),
+			},
+			Scopes: []types.PermissionScope{
+				types.UserScope,
+				types.ProjectScope,
+				types.ClusterScope,
+				types.NamespaceScope,
+			},
+		},
+	)
+
+	getJobPodsHandler := jobs.NewGetPodsHandler(
+		config,
+		factory.GetResultWriter(),
+	)
+
+	routes = append(routes, &Route{
+		Endpoint: getJobPodsEndpoint,
+		Handler:  getJobPodsHandler,
+		Router:   r,
+	})
+
+	// DELETE /api/projects/{project_id}/clusters/{cluster_id}/namespaces/{namespace}/jobs/{name} -> jobs.NewDeleteHandler
+	deleteJobEndpoint := factory.NewAPIEndpoint(
+		&types.APIRequestMetadata{
+			Verb:   types.APIVerbDelete,
+			Method: types.HTTPVerbDelete,
+			Path: &types.Path{
+				Parent: basePath,
+				RelativePath: fmt.Sprintf(
+					"%s/jobs/{%s}",
+					relPath,
+					types.URLParamJobName,
+				),
+			},
+			Scopes: []types.PermissionScope{
+				types.UserScope,
+				types.ProjectScope,
+				types.ClusterScope,
+				types.NamespaceScope,
+			},
+		},
+	)
+
+	deleteJobHandler := jobs.NewDeleteHandler(
+		config,
+	)
+
+	routes = append(routes, &Route{
+		Endpoint: deleteJobEndpoint,
+		Handler:  deleteJobHandler,
+		Router:   r,
+	})
+
+	// POST /api/projects/{project_id}/clusters/{cluster_id}/namespaces/{namespace}/jobs/{name}/stop -> jobs.NewStopHandler
+	stopJobEndpoint := factory.NewAPIEndpoint(
+		&types.APIRequestMetadata{
+			Verb:   types.APIVerbUpdate,
+			Method: types.HTTPVerbPost,
+			Path: &types.Path{
+				Parent: basePath,
+				RelativePath: fmt.Sprintf(
+					"%s/jobs/{%s}/stop",
+					relPath,
+					types.URLParamJobName,
+				),
+			},
+			Scopes: []types.PermissionScope{
+				types.UserScope,
+				types.ProjectScope,
+				types.ClusterScope,
+				types.NamespaceScope,
+			},
+		},
+	)
+
+	stopJobHandler := jobs.NewStopHandler(
+		config,
+	)
+
+	routes = append(routes, &Route{
+		Endpoint: stopJobEndpoint,
+		Handler:  stopJobHandler,
+		Router:   r,
+	})
+
 	return routes, newPath
 }

+ 5 - 0
api/types/jobs.go

@@ -0,0 +1,5 @@
+package types
+
+const (
+	URLParamJobName URLParam = "name"
+)

+ 1 - 1
dashboard/src/main/home/cluster-dashboard/expanded-chart/ExpandedJobChart.tsx

@@ -216,7 +216,7 @@ class ExpandedJobChart extends Component<PropsType, StateType> {
     let { currentCluster, currentProject } = this.context;
     let protocol = window.location.protocol == "https:" ? "wss" : "ws";
     let ws = new WebSocket(
-      `${protocol}://${window.location.host}/api/projects/${currentProject.id}/k8s/cronjob/status?cluster_id=${currentCluster.id}`
+      `${protocol}://${window.location.host}/api/projects/${currentProject.id}/clusters/${currentCluster.id}/cronjob/status`
     );
     ws.onopen = () => {
       console.log("connected to websocket");

+ 1 - 1
dashboard/src/main/home/cluster-dashboard/expanded-chart/jobs/JobList.tsx

@@ -66,11 +66,11 @@ class JobList extends Component<PropsType, StateType> {
       .deleteJob(
         "<token>",
         {
-          cluster_id: currentCluster.id,
         },
         {
           id: currentProject.id,
           name: job.metadata?.name,
+          cluster_id: currentCluster.id,
           namespace: job.metadata?.namespace,
         }
       )

+ 1 - 1
dashboard/src/main/home/cluster-dashboard/expanded-chart/jobs/JobResource.tsx

@@ -75,11 +75,11 @@ export default class JobResource extends Component<PropsType, StateType> {
       .getJobPods(
         "<token>",
         {
-          cluster_id: currentCluster.id,
         },
         {
           id: currentProject.id,
           name: this.props.job.metadata?.name,
+          cluster_id: currentCluster.id,
           namespace: this.props.job.metadata?.namespace,
         }
       )

+ 9 - 8
dashboard/src/shared/api.tsx

@@ -571,11 +571,11 @@ const getJobStatus = baseApi<
 
 const getJobPods = baseApi<
   {
-    cluster_id: number;
   },
-  { name: string; namespace: string; id: number }
+  { name: string; namespace: string; id: number; cluster_id: number; }
 >("GET", (pathParams) => {
-  return `/api/projects/${pathParams.id}/k8s/jobs/${pathParams.namespace}/${pathParams.name}/pods`;
+  let { id, name, cluster_id, namespace } = pathParams
+  return `/api/projects/${id}/clusters/${cluster_id}/namespaces/${namespace}/jobs/${name}/pods`;
 });
 
 const getMatchingPods = baseApi<
@@ -973,11 +973,12 @@ const deleteNamespace = baseApi<
 });
 
 const deleteJob = baseApi<
-  { cluster_id: number },
-  { name: string; namespace: string; id: number }
+{
+},
+{ name: string; namespace: string; id: number; cluster_id: number; }
 >("DELETE", (pathParams) => {
-  let { id, name, namespace } = pathParams;
-  return `/api/projects/${id}/k8s/jobs/${namespace}/${name}`;
+  let { id, name, cluster_id, namespace } = pathParams
+  return `/api/projects/${id}/clusters/${cluster_id}/namespaces/${namespace}/jobs/${name}`;
 });
 
 const stopJob = baseApi<
@@ -985,7 +986,7 @@ const stopJob = baseApi<
   { name: string; namespace: string; id: number; cluster_id: number }
 >("POST", (pathParams) => {
   let { id, name, namespace, cluster_id } = pathParams;
-  return `/api/projects/${id}/k8s/jobs/${namespace}/${name}/stop?cluster_id=${cluster_id}`;
+  return `/api/projects/${id}/clusters/${cluster_id}/namespaces/${namespace}/jobs/${name}/stop`
 });
 
 const getAvailableRoles = baseApi<{}, { project_id: number }>(

+ 3 - 3
docs/developing/backend-refactor-status.md

@@ -84,9 +84,9 @@
 | <li>- [x] `POST /api/projects/{project_id}/k8s/configmap/rename`                                                            | AS          | yes             |             | yes              |
 | <li>- [x] `POST /api/projects/{project_id}/k8s/configmap/update`                                                            | AS          | yes             |             | yes              |
 | <li>- [X] `GET /api/projects/{project_id}/k8s/helm_releases`                                                                | AB          | yes             |             |                  |
-| <li>- [ ] `DELETE /api/projects/{project_id}/k8s/jobs/{namespace}/{name}`                                                   |             |                 |             |                  |
-| <li>- [ ] `GET /api/projects/{project_id}/k8s/jobs/{namespace}/{name}/pods`                                                 |             |                 |             |                  |
-| <li>- [ ] `POST /api/projects/{project_id}/k8s/jobs/{namespace}/{name}/stop`                                                |             |                 |             |                  |
+| <li>- [X] `DELETE /api/projects/{project_id}/k8s/jobs/{namespace}/{name}`                                                   | AB          |                 |             |                  |
+| <li>- [X] `GET /api/projects/{project_id}/k8s/jobs/{namespace}/{name}/pods`                                                 | AB          |                 |             |                  |
+| <li>- [X] `POST /api/projects/{project_id}/k8s/jobs/{namespace}/{name}/stop`                                                | AB          |                 |             |                  |
 | <li>- [x] `GET /api/projects/{project_id}/k8s/kubeconfig`                                                                   | AS          | yes             | yes         |                  |
 | <li>- [x] `GET /api/projects/{project_id}/k8s/metrics`                                                                      | AS          | yes             |             | yes              |
 | <li>- [x] `GET /api/projects/{project_id}/k8s/namespaces`                                                                   | AS          | yes             |             | yes              |