diff --git a/frontend/src/pages/K8sResourceList.tsx b/frontend/src/pages/K8sResourceList.tsx
index e201ddb..c635edd 100644
--- a/frontend/src/pages/K8sResourceList.tsx
+++ b/frontend/src/pages/K8sResourceList.tsx
@@ -198,6 +198,10 @@ export default function K8sResourceList() {
try {
let endpoint = '';
let kind = '';
+ let requestBody = {
+ name: deleteTarget.name,
+ namespace: deleteTarget.namespace
+ };
// Determine the correct endpoint based on the selected resource kind
switch (selectedKind.key) {
@@ -221,6 +225,12 @@ export default function K8sResourceList() {
endpoint = '/api/v1/k8s/configmap/delete'
kind = 'ConfigMap'
break
+ case 'namespace':
+ endpoint = '/api/v1/k8s/namespace/delete'
+ kind = 'Namespace'
+ // Namespace doesn't need namespace field
+ requestBody = { name: deleteTarget.name }
+ break
default:
throw new Error(`Unsupported resource kind: ${selectedKind.key}`)
}
@@ -228,10 +238,7 @@ export default function K8sResourceList() {
const res = await fetch(endpoint, {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({
- name: deleteTarget.name,
- namespace: deleteTarget.namespace
- }),
+ body: JSON.stringify(requestBody),
})
const result = await res.json()
@@ -381,7 +388,7 @@ export default function K8sResourceList() {
const getResourceColumns = () => {
switch (selectedKind.key) {
case 'namespace':
- return ['Name', 'Status', 'Age']
+ return ['Name', 'Status', 'Age', 'Actions']
case 'deployment':
case 'statefulset':
return ['Name', 'Namespace', 'Replicas', 'Age', 'Actions']
@@ -421,6 +428,17 @@ export default function K8sResourceList() {
{metadata.name || '-'}
{status.phase || '-'}
{getAge(metadata.creationTimestamp)}
+
+
+ openDeleteDialog(metadata.name, metadata.namespace)}
+ >
+
+
+
+
)
case 'deployment':
diff --git a/internal/api/api.go b/internal/api/api.go
index 8271afe..9ac6ce2 100644
--- a/internal/api/api.go
+++ b/internal/api/api.go
@@ -71,6 +71,7 @@ func Init(ctx context.Context, address string, db *gorm.DB, store store.Store) (
k8sAPI.Post("/resource/update", k8s.K8sResourceUpdate(ctx, db, store))
// resource list
k8sAPI.Get("/namespace/list", k8s.K8sNamespaceList(ctx, db, store))
+ k8sAPI.Delete("/namespace/delete", k8s.K8sNamespaceDelete(ctx, db, store))
k8sAPI.Get("/deployment/list", k8s.K8sDeploymentList(ctx, db, store))
k8sAPI.Delete("/deployment/delete", k8s.K8sDeploymentDelete(ctx, db, store))
k8sAPI.Get("/statefulset/list", k8s.K8sStatefulSetList(ctx, db, store))
diff --git a/internal/module/k8s/handler.resource.go b/internal/module/k8s/handler.resource.go
index 2ecc8b1..8fcb4a1 100644
--- a/internal/module/k8s/handler.resource.go
+++ b/internal/module/k8s/handler.resource.go
@@ -927,3 +927,33 @@ func K8sConfigMapDelete(ctx context.Context, db *gorm.DB, store store.Store) fib
})
}
}
+
+func K8sNamespaceDelete(ctx context.Context, db *gorm.DB, store store.Store) fiber.Handler {
+ return func(c fiber.Ctx) error {
+ var req struct {
+ Name string `json:"name"`
+ }
+
+ if err := json.Unmarshal(c.Body(), &req); err != nil {
+ return resp.R400(c, "", nil, err)
+ }
+
+ if req.Name == "" {
+ return resp.R400(c, "", nil, fmt.Errorf("name is required"))
+ }
+
+ clientset, err := getK8sClient(db)
+ if err != nil {
+ return resp.R500(c, "", nil, err)
+ }
+
+ err = clientset.CoreV1().Namespaces().Delete(c.Context(), req.Name, metav1.DeleteOptions{})
+ if err != nil {
+ return resp.R500(c, "", nil, fmt.Errorf("failed to delete namespace: %w", err))
+ }
+
+ return resp.R200(c, map[string]any{
+ "name": req.Name,
+ })
+ }
+}