diff --git a/pkg/kubernetes/pods.go b/pkg/kubernetes/pods.go index ada91826..6a728a8b 100644 --- a/pkg/kubernetes/pods.go +++ b/pkg/kubernetes/pods.go @@ -77,10 +77,11 @@ func (k *Kubernetes) PodsDelete(ctx context.Context, namespace, name string) (st k.clientSet.CoreV1().Pods(namespace).Delete(ctx, name, metav1.DeleteOptions{}) } -func (k *Kubernetes) PodsLog(ctx context.Context, namespace, name string) (string, error) { +func (k *Kubernetes) PodsLog(ctx context.Context, namespace, name, container string) (string, error) { tailLines := int64(256) req := k.clientSet.CoreV1().Pods(namespaceOrDefault(namespace)).GetLogs(name, &v1.PodLogOptions{ TailLines: &tailLines, + Container: container, }) res := req.Do(ctx) if res.Error() != nil { diff --git a/pkg/mcp/pods.go b/pkg/mcp/pods.go index 8508d690..0d3f72a0 100644 --- a/pkg/mcp/pods.go +++ b/pkg/mcp/pods.go @@ -49,6 +49,7 @@ func (s *Server) initPods() []server.ServerTool { mcp.WithDescription("Get the logs of a Kubernetes Pod in the current or provided namespace with the provided name"), mcp.WithString("namespace", mcp.Description("Namespace to get the Pod logs from")), mcp.WithString("name", mcp.Description("Name of the Pod to get the logs from"), mcp.Required()), + mcp.WithString("container", mcp.Description("Name of the Pod container to get the logs from (Optional)")), ), s.podsLog}, {mcp.NewTool("pods_run", mcp.WithDescription("Run a Kubernetes Pod in the current or provided namespace with the provided container image and optional name"), @@ -150,7 +151,11 @@ func (s *Server) podsLog(ctx context.Context, ctr mcp.CallToolRequest) (*mcp.Cal if name == nil { return NewTextResult("", errors.New("failed to get pod log, missing argument name")), nil } - ret, err := s.k.PodsLog(ctx, ns.(string), name.(string)) + container := ctr.Params.Arguments["container"] + if container == nil { + container = "" + } + ret, err := s.k.PodsLog(ctx, ns.(string), name.(string), container.(string)) if err != nil { return NewTextResult("", fmt.Errorf("failed to get pod %s log in namespace %s: %v", name, ns, err)), nil } else if ret == "" { diff --git a/pkg/mcp/pods_test.go b/pkg/mcp/pods_test.go index b7ca84e1..5c2898ec 100644 --- a/pkg/mcp/pods_test.go +++ b/pkg/mcp/pods_test.go @@ -526,6 +526,36 @@ func TestPodsLog(t *testing.T) { return } }) + podsContainerLogInNamespace, err := c.callTool("pods_log", map[string]interface{}{ + "namespace": "ns-1", + "name": "a-pod-in-ns-1", + "container": "nginx", + }) + t.Run("pods_log with name, container and namespace returns pod log", func(t *testing.T) { + if err != nil { + t.Fatalf("call tool failed %v", err) + return + } + if podsContainerLogInNamespace.IsError { + t.Fatalf("call tool failed") + return + } + }) + toolResult, err := c.callTool("pods_log", map[string]interface{}{ + "namespace": "ns-1", + "name": "a-pod-in-ns-1", + "container": "a-not-existing-container", + }) + t.Run("pods_log with non existing container returns error", func(t *testing.T) { + if toolResult.IsError != true { + t.Fatalf("call tool should fail") + return + } + if toolResult.Content[0].(mcp.TextContent).Text != "failed to get pod a-pod-in-ns-1 log in namespace ns-1: container a-not-existing-container is not valid for pod a-pod-in-ns-1" { + t.Fatalf("invalid error message, got %v", toolResult.Content[0].(mcp.TextContent).Text) + return + } + }) }) }