Skip to content

Commit fcb2992

Browse files
committed
test(kubernetes): split TestPodsTop to avoid discovery client cache issues
1 parent af056ae commit fcb2992

File tree

1 file changed

+40
-32
lines changed

1 file changed

+40
-32
lines changed

pkg/mcp/pods_top_test.go

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,53 @@ import (
44
"github.com/mark3labs/mcp-go/mcp"
55
"net/http"
66
"regexp"
7-
"sync"
87
"testing"
98
)
109

11-
func TestPodsTop(t *testing.T) {
10+
func TestPodsTopMetricsUnavailable(t *testing.T) {
11+
testCase(t, func(c *mcpContext) {
12+
mockServer := NewMockServer()
13+
defer mockServer.Close()
14+
c.withKubeConfig(mockServer.config)
15+
mockServer.Handle(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
16+
w.Header().Set("Content-Type", "application/json")
17+
// Request Performed by DiscoveryClient to Kube API (Get API Groups legacy -core-)
18+
if req.URL.Path == "/api" {
19+
_, _ = w.Write([]byte(`{"kind":"APIVersions","versions":[],"serverAddressByClientCIDRs":[{"clientCIDR":"0.0.0.0/0"}]}`))
20+
return
21+
}
22+
// Request Performed by DiscoveryClient to Kube API (Get API Groups)
23+
if req.URL.Path == "/apis" {
24+
_, _ = w.Write([]byte(`{"kind":"APIGroupList","apiVersion":"v1","groups":[]}`))
25+
return
26+
}
27+
}))
28+
podsTopMetricsApiUnavailable, err := c.callTool("pods_top", map[string]interface{}{})
29+
t.Run("pods_top with metrics API not available", func(t *testing.T) {
30+
if err != nil {
31+
t.Fatalf("call tool failed %v", err)
32+
}
33+
if !podsTopMetricsApiUnavailable.IsError {
34+
t.Errorf("call tool should have returned an error")
35+
}
36+
if podsTopMetricsApiUnavailable.Content[0].(mcp.TextContent).Text != "failed to get pods top: metrics API is not available" {
37+
t.Errorf("call tool returned unexpected content: %s", podsTopMetricsApiUnavailable.Content[0].(mcp.TextContent).Text)
38+
}
39+
})
40+
})
41+
}
42+
43+
func TestPodsTopMetricsAvailable(t *testing.T) {
1244
testCase(t, func(c *mcpContext) {
1345
mockServer := NewMockServer()
1446
defer mockServer.Close()
1547
c.withKubeConfig(mockServer.config)
16-
metricsApiAvailable := false
17-
metricsApiMutex := sync.Mutex{}
1848
mockServer.Handle(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
1949
println("Request received:", req.Method, req.URL.Path) // TODO: REMOVE LINE
2050
w.Header().Set("Content-Type", "application/json")
2151
// Request Performed by DiscoveryClient to Kube API (Get API Groups legacy -core-)
2252
if req.URL.Path == "/api" {
23-
if !metricsApiAvailable {
24-
_, _ = w.Write([]byte(`{"kind":"APIVersions","versions":[],"serverAddressByClientCIDRs":[{"clientCIDR":"0.0.0.0/0"}]}`))
25-
} else {
26-
_, _ = w.Write([]byte(`{"kind":"APIVersions","versions":["metrics.k8s.io/v1beta1"],"serverAddressByClientCIDRs":[{"clientCIDR":"0.0.0.0/0"}]}`))
27-
}
53+
_, _ = w.Write([]byte(`{"kind":"APIVersions","versions":["metrics.k8s.io/v1beta1"],"serverAddressByClientCIDRs":[{"clientCIDR":"0.0.0.0/0"}]}`))
2854
return
2955
}
3056
// Request Performed by DiscoveryClient to Kube API (Get API Groups)
@@ -33,12 +59,12 @@ func TestPodsTop(t *testing.T) {
3359
return
3460
}
3561
// Request Performed by DiscoveryClient to Kube API (Get API Resources)
36-
if metricsApiAvailable && req.URL.Path == "/apis/metrics.k8s.io/v1beta1" {
62+
if req.URL.Path == "/apis/metrics.k8s.io/v1beta1" {
3763
_, _ = w.Write([]byte(`{"kind":"APIResourceList","apiVersion":"v1","groupVersion":"metrics.k8s.io/v1beta1","resources":[{"name":"pods","singularName":"","namespaced":true,"kind":"PodMetrics","verbs":["get","list"]}]}`))
3864
return
3965
}
4066
// Pod Metrics from all namespaces
41-
if metricsApiAvailable && req.URL.Path == "/apis/metrics.k8s.io/v1beta1/pods" {
67+
if req.URL.Path == "/apis/metrics.k8s.io/v1beta1/pods" {
4268
if req.URL.Query().Get("labelSelector") == "app=pod-ns-5-42" {
4369
_, _ = w.Write([]byte(`{"kind":"PodMetricsList","apiVersion":"metrics.k8s.io/v1beta1","items":[` +
4470
`{"metadata":{"name":"pod-ns-5-42","namespace":"ns-5"},"containers":[{"name":"container-1","usage":{"cpu":"42m","memory":"42Mi"}}]}` +
@@ -53,46 +79,28 @@ func TestPodsTop(t *testing.T) {
5379
return
5480
}
5581
// Pod Metrics from configured namespace
56-
if metricsApiAvailable && req.URL.Path == "/apis/metrics.k8s.io/v1beta1/namespaces/default/pods" {
82+
if req.URL.Path == "/apis/metrics.k8s.io/v1beta1/namespaces/default/pods" {
5783
_, _ = w.Write([]byte(`{"kind":"PodMetricsList","apiVersion":"metrics.k8s.io/v1beta1","items":[` +
5884
`{"metadata":{"name":"pod-1","namespace":"default"},"containers":[{"name":"container-1","usage":{"cpu":"10m","memory":"20Mi"}},{"name":"container-2","usage":{"cpu":"30m","memory":"40Mi"}}]}` +
5985
`]}`))
6086
return
6187
}
6288
// Pod Metrics from ns-5 namespace
63-
if metricsApiAvailable && req.URL.Path == "/apis/metrics.k8s.io/v1beta1/namespaces/ns-5/pods" {
89+
if req.URL.Path == "/apis/metrics.k8s.io/v1beta1/namespaces/ns-5/pods" {
6490
_, _ = w.Write([]byte(`{"kind":"PodMetricsList","apiVersion":"metrics.k8s.io/v1beta1","items":[` +
6591
`{"metadata":{"name":"pod-ns-5-1","namespace":"ns-5"},"containers":[{"name":"container-1","usage":{"cpu":"10m","memory":"20Mi"}}]}` +
6692
`]}`))
6793
return
6894
}
6995
// Pod Metrics from ns-5 namespace with pod-ns-5-5 pod name
70-
if metricsApiAvailable && req.URL.Path == "/apis/metrics.k8s.io/v1beta1/namespaces/ns-5/pods/pod-ns-5-5" {
96+
if req.URL.Path == "/apis/metrics.k8s.io/v1beta1/namespaces/ns-5/pods/pod-ns-5-5" {
7197
_, _ = w.Write([]byte(`{"kind":"PodMetrics","apiVersion":"metrics.k8s.io/v1beta1",` +
7298
`"metadata":{"name":"pod-ns-5-5","namespace":"ns-5"},` +
7399
`"containers":[{"name":"container-1","usage":{"cpu":"13m","memory":"37Mi"}}]` +
74100
`}`))
75101
}
76102
}))
77-
metricsApiMutex.Lock()
78-
podsTopMetricsApiUnavailable, err := c.callTool("pods_top", map[string]interface{}{})
79-
metricsApiMutex.Unlock()
80-
t.Run("pods_top with metrics API not available", func(t *testing.T) {
81-
if err != nil {
82-
t.Fatalf("call tool failed %v", err)
83-
}
84-
if !podsTopMetricsApiUnavailable.IsError {
85-
t.Errorf("call tool should have returned an error")
86-
}
87-
if podsTopMetricsApiUnavailable.Content[0].(mcp.TextContent).Text != "failed to get pods top: metrics API is not available" {
88-
t.Errorf("call tool returned unexpected content: %s", podsTopMetricsApiUnavailable.Content[0].(mcp.TextContent).Text)
89-
}
90-
})
91-
// Enable metrics API addon
92-
metricsApiMutex.Lock()
93-
metricsApiAvailable = true
94103
podsTopDefaults, err := c.callTool("pods_top", map[string]interface{}{})
95-
metricsApiMutex.Unlock()
96104
t.Run("pods_top defaults returns pod metrics from all namespaces", func(t *testing.T) {
97105
if err != nil {
98106
t.Fatalf("call tool failed %v", err)

0 commit comments

Comments
 (0)