Skip to content

Commit 40ff50e

Browse files
committed
feat(kubernetes): pods_delete deletes managed resources
1 parent 838e586 commit 40ff50e

File tree

5 files changed

+297
-30
lines changed

5 files changed

+297
-30
lines changed

pkg/kubernetes/pods.go

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import (
66
v1 "k8s.io/api/core/v1"
77
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
88
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
9+
labelutil "k8s.io/apimachinery/pkg/labels"
910
"k8s.io/apimachinery/pkg/runtime"
1011
"k8s.io/apimachinery/pkg/runtime/schema"
1112
"k8s.io/apimachinery/pkg/util/intstr"
1213
"k8s.io/apimachinery/pkg/util/rand"
14+
"k8s.io/client-go/dynamic"
1315
"k8s.io/client-go/kubernetes"
1416
)
1517

@@ -32,8 +34,53 @@ func (k *Kubernetes) PodsGet(ctx context.Context, namespace, name string) (strin
3234
}
3335

3436
func (k *Kubernetes) PodsDelete(ctx context.Context, namespace, name string) (string, error) {
35-
// TODO
36-
return "", nil
37+
cs, err := kubernetes.NewForConfig(k.cfg)
38+
if err != nil {
39+
return "", err
40+
}
41+
42+
namespace = namespaceOrDefault(namespace)
43+
pod, err := cs.CoreV1().Pods(namespace).Get(ctx, name, metav1.GetOptions{})
44+
if err != nil {
45+
return "", err
46+
}
47+
48+
isManaged := pod.GetLabels()[AppKubernetesManagedBy] == version.BinaryName
49+
managedLabelSelector := labelutil.Set{
50+
AppKubernetesManagedBy: version.BinaryName,
51+
AppKubernetesName: pod.GetLabels()[AppKubernetesName],
52+
}.AsSelector()
53+
54+
// Delete managed service
55+
if isManaged {
56+
if sl, _ := cs.CoreV1().Services(namespace).List(ctx, metav1.ListOptions{
57+
LabelSelector: managedLabelSelector.String(),
58+
}); sl != nil {
59+
for _, svc := range sl.Items {
60+
_ = cs.CoreV1().Services(namespace).Delete(ctx, svc.Name, metav1.DeleteOptions{})
61+
}
62+
}
63+
}
64+
65+
// Delete managed Route
66+
if isManaged && k.supportsGroupVersion("route.openshift.io/v1") {
67+
dynamicClient, dErr := dynamic.NewForConfig(k.cfg)
68+
if dErr != nil {
69+
return "", dErr
70+
}
71+
routeResources := dynamicClient.
72+
Resource(schema.GroupVersionResource{Group: "route.openshift.io", Version: "v1", Resource: "routes"}).
73+
Namespace(namespace)
74+
if rl, _ := routeResources.List(ctx, metav1.ListOptions{
75+
LabelSelector: managedLabelSelector.String(),
76+
}); rl != nil {
77+
for _, route := range rl.Items {
78+
_ = routeResources.Delete(ctx, route.GetName(), metav1.DeleteOptions{})
79+
}
80+
}
81+
82+
}
83+
return "Pod deleted successfully", cs.CoreV1().Pods(namespace).Delete(ctx, name, metav1.DeleteOptions{})
3784
}
3885

3986
func (k *Kubernetes) PodsLog(ctx context.Context, namespace, name string) (string, error) {

pkg/mcp/common_test.go

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -231,33 +231,18 @@ func createTestData(ctx context.Context, kc *kubernetes.Clientset) {
231231
Create(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "ns-2"}}, metav1.CreateOptions{})
232232
_, _ = kc.CoreV1().Namespaces().
233233
Create(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "ns-to-delete"}}, metav1.CreateOptions{})
234-
_, _ = kc.CoreV1().Pods("default").
235-
Create(ctx, &corev1.Pod{
236-
ObjectMeta: metav1.ObjectMeta{Name: "a-pod-in-default"},
237-
Spec: corev1.PodSpec{
238-
Containers: []corev1.Container{
239-
{Name: "nginx", Image: "nginx"},
240-
},
241-
},
242-
}, metav1.CreateOptions{})
243-
_, _ = kc.CoreV1().Pods("ns-1").
244-
Create(ctx, &corev1.Pod{
245-
ObjectMeta: metav1.ObjectMeta{Name: "a-pod-in-ns-1"},
246-
Spec: corev1.PodSpec{
247-
Containers: []corev1.Container{
248-
{Name: "nginx", Image: "nginx"},
249-
},
250-
},
251-
}, metav1.CreateOptions{})
252-
_, _ = kc.CoreV1().Pods("ns-2").
253-
Create(ctx, &corev1.Pod{
254-
ObjectMeta: metav1.ObjectMeta{Name: "a-pod-in-ns-2"},
255-
Spec: corev1.PodSpec{
256-
Containers: []corev1.Container{
257-
{Name: "nginx", Image: "nginx"},
258-
},
259-
},
260-
}, metav1.CreateOptions{})
234+
_, _ = kc.CoreV1().Pods("default").Create(ctx, &corev1.Pod{
235+
ObjectMeta: metav1.ObjectMeta{Name: "a-pod-in-default"},
236+
Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "nginx", Image: "nginx"}}},
237+
}, metav1.CreateOptions{})
238+
_, _ = kc.CoreV1().Pods("ns-1").Create(ctx, &corev1.Pod{
239+
ObjectMeta: metav1.ObjectMeta{Name: "a-pod-in-ns-1"},
240+
Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "nginx", Image: "nginx"}}},
241+
}, metav1.CreateOptions{})
242+
_, _ = kc.CoreV1().Pods("ns-2").Create(ctx, &corev1.Pod{
243+
ObjectMeta: metav1.ObjectMeta{Name: "a-pod-in-ns-2"},
244+
Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "nginx", Image: "nginx"}}},
245+
}, metav1.CreateOptions{})
261246
_, _ = kc.CoreV1().ConfigMaps("default").
262247
Create(ctx, &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "a-configmap-to-delete"}}, metav1.CreateOptions{})
263248
}

pkg/mcp/mcp_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ func TestTools(t *testing.T) {
1111
"pods_list",
1212
"pods_list_in_namespace",
1313
"pods_get",
14+
"pods_delete",
1415
"pods_log",
1516
"pods_run",
1617
"resources_list",

pkg/mcp/pods.go

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,25 @@ func (s *Sever) initPods() {
3232
mcp.Required(),
3333
),
3434
), podsGet)
35+
s.server.AddTool(mcp.NewTool(
36+
"pods_delete",
37+
mcp.WithDescription("Delete a Kubernetes Pod in the current or provided namespace with the provided name"),
38+
mcp.WithString("namespace",
39+
mcp.Description("Namespace to delete the Pod from"),
40+
),
41+
mcp.WithString("name",
42+
mcp.Description("Name of the Pod to delete"),
43+
mcp.Required(),
44+
),
45+
), podsDelete)
3546
s.server.AddTool(mcp.NewTool(
3647
"pods_log",
3748
mcp.WithDescription("Get the logs of a Kubernetes Pod in the current or provided namespace with the provided name"),
3849
mcp.WithString("namespace",
3950
mcp.Description("Namespace to get the Pod logs from"),
4051
),
4152
mcp.WithString("name",
42-
mcp.Description("Name of the Pod"),
53+
mcp.Description("Name of the Pod to get the logs from"),
4354
mcp.Required(),
4455
),
4556
), podsLog)
@@ -110,6 +121,26 @@ func podsGet(ctx context.Context, ctr mcp.CallToolRequest) (*mcp.CallToolResult,
110121
return NewTextResult(ret, err), nil
111122
}
112123

124+
func podsDelete(ctx context.Context, ctr mcp.CallToolRequest) (*mcp.CallToolResult, error) {
125+
k, err := kubernetes.NewKubernetes()
126+
if err != nil {
127+
return NewTextResult("", fmt.Errorf("failed to delete pod: %v", err)), nil
128+
}
129+
ns := ctr.Params.Arguments["namespace"]
130+
if ns == nil {
131+
ns = ""
132+
}
133+
name := ctr.Params.Arguments["name"]
134+
if name == nil {
135+
return NewTextResult("", errors.New("failed to delete pod, missing argument name")), nil
136+
}
137+
ret, err := k.PodsDelete(ctx, ns.(string), name.(string))
138+
if err != nil {
139+
return NewTextResult("", fmt.Errorf("failed to delete pod %s in namespace %s: %v", name, ns, err)), nil
140+
}
141+
return NewTextResult(ret, err), nil
142+
}
143+
113144
func podsLog(ctx context.Context, ctr mcp.CallToolRequest) (*mcp.CallToolResult, error) {
114145
k, err := kubernetes.NewKubernetes()
115146
if err != nil {

0 commit comments

Comments
 (0)