kubernetes-mcp-server
by manusa
Verified
- kubernetes-mcp-server
- pkg
- kubernetes
package kubernetes
import (
"context"
"github.com/manusa/kubernetes-mcp-server/pkg/version"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
labelutil "k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/rand"
)
func (k *Kubernetes) PodsListInAllNamespaces(ctx context.Context) (string, error) {
return k.ResourcesList(ctx, &schema.GroupVersionKind{
Group: "", Version: "v1", Kind: "Pod",
}, "")
}
func (k *Kubernetes) PodsListInNamespace(ctx context.Context, namespace string) (string, error) {
return k.ResourcesList(ctx, &schema.GroupVersionKind{
Group: "", Version: "v1", Kind: "Pod",
}, namespace)
}
func (k *Kubernetes) PodsGet(ctx context.Context, namespace, name string) (string, error) {
return k.ResourcesGet(ctx, &schema.GroupVersionKind{
Group: "", Version: "v1", Kind: "Pod",
}, namespaceOrDefault(namespace), name)
}
func (k *Kubernetes) PodsDelete(ctx context.Context, namespace, name string) (string, error) {
namespace = namespaceOrDefault(namespace)
pod, err := k.clientSet.CoreV1().Pods(namespace).Get(ctx, name, metav1.GetOptions{})
if err != nil {
return "", err
}
isManaged := pod.GetLabels()[AppKubernetesManagedBy] == version.BinaryName
managedLabelSelector := labelutil.Set{
AppKubernetesManagedBy: version.BinaryName,
AppKubernetesName: pod.GetLabels()[AppKubernetesName],
}.AsSelector()
// Delete managed service
if isManaged {
if sl, _ := k.clientSet.CoreV1().Services(namespace).List(ctx, metav1.ListOptions{
LabelSelector: managedLabelSelector.String(),
}); sl != nil {
for _, svc := range sl.Items {
_ = k.clientSet.CoreV1().Services(namespace).Delete(ctx, svc.Name, metav1.DeleteOptions{})
}
}
}
// Delete managed Route
if isManaged && k.supportsGroupVersion("route.openshift.io/v1") {
routeResources := k.dynamicClient.
Resource(schema.GroupVersionResource{Group: "route.openshift.io", Version: "v1", Resource: "routes"}).
Namespace(namespace)
if rl, _ := routeResources.List(ctx, metav1.ListOptions{
LabelSelector: managedLabelSelector.String(),
}); rl != nil {
for _, route := range rl.Items {
_ = routeResources.Delete(ctx, route.GetName(), metav1.DeleteOptions{})
}
}
}
return "Pod deleted successfully",
k.clientSet.CoreV1().Pods(namespace).Delete(ctx, name, metav1.DeleteOptions{})
}
func (k *Kubernetes) PodsLog(ctx context.Context, namespace, name string) (string, error) {
tailLines := int64(256)
req := k.clientSet.CoreV1().Pods(namespaceOrDefault(namespace)).GetLogs(name, &v1.PodLogOptions{
TailLines: &tailLines,
})
res := req.Do(ctx)
if res.Error() != nil {
return "", res.Error()
}
rawData, err := res.Raw()
if err != nil {
return "", err
}
return string(rawData), nil
}
func (k *Kubernetes) PodsRun(ctx context.Context, namespace, name, image string, port int32) (string, error) {
if name == "" {
name = version.BinaryName + "-run-" + rand.String(5)
}
labels := map[string]string{
AppKubernetesName: name,
AppKubernetesComponent: name,
AppKubernetesManagedBy: version.BinaryName,
AppKubernetesPartOf: version.BinaryName + "-run-sandbox",
}
// NewPod
var resources []any
pod := &v1.Pod{
TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"},
ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespaceOrDefault(namespace), Labels: labels},
Spec: v1.PodSpec{Containers: []v1.Container{{
Name: name,
Image: image,
ImagePullPolicy: v1.PullAlways,
}}},
}
resources = append(resources, pod)
if port > 0 {
pod.Spec.Containers[0].Ports = []v1.ContainerPort{{ContainerPort: port}}
resources = append(resources, &v1.Service{
TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Service"},
ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespaceOrDefault(namespace), Labels: labels},
Spec: v1.ServiceSpec{
Selector: labels,
Type: v1.ServiceTypeClusterIP,
Ports: []v1.ServicePort{{Port: port, TargetPort: intstr.FromInt32(port)}},
},
})
}
if port > 0 && k.supportsGroupVersion("route.openshift.io/v1") {
resources = append(resources, &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "route.openshift.io/v1",
"kind": "Route",
"metadata": map[string]interface{}{
"name": name,
"namespace": namespaceOrDefault(namespace),
"labels": labels,
},
"spec": map[string]interface{}{
"to": map[string]interface{}{
"kind": "Service",
"name": name,
"weight": 100,
},
"port": map[string]interface{}{
"targetPort": intstr.FromInt32(port),
},
"tls": map[string]interface{}{
"termination": "edge",
"insecureEdgeTerminationPolicy": "Redirect",
},
},
},
})
}
// Convert the objects to Unstructured and reuse resourcesCreateOrUpdate functionality
converter := runtime.DefaultUnstructuredConverter
var toCreate []*unstructured.Unstructured
for _, obj := range resources {
m, err := converter.ToUnstructured(obj)
if err != nil {
return "", err
}
u := &unstructured.Unstructured{}
if err = converter.FromUnstructured(m, u); err != nil {
return "", err
}
toCreate = append(toCreate, u)
}
return k.resourcesCreateOrUpdate(ctx, toCreate)
}