mirror of
https://github.com/containers/kubernetes-mcp-server.git
synced 2025-10-23 01:22:57 +03:00
test(toolsets): toolset specific metadata tests (#326)
- Refactor tests to use testify (more clarity+composability for complex tests) - Tests for default toolsets - Tests for configured, granular toolsets Signed-off-by: Marc Nuri <marc@marcnuri.com>
This commit is contained in:
22
internal/test/kubernetes.go
Normal file
22
internal/test/kubernetes.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
)
|
||||
|
||||
func KubeConfigFake() *clientcmdapi.Config {
|
||||
fakeConfig := clientcmdapi.NewConfig()
|
||||
fakeConfig.Clusters["fake"] = clientcmdapi.NewCluster()
|
||||
fakeConfig.Clusters["fake"].Server = "https://127.0.0.1:6443"
|
||||
fakeConfig.Clusters["additional-cluster"] = clientcmdapi.NewCluster()
|
||||
fakeConfig.AuthInfos["fake"] = clientcmdapi.NewAuthInfo()
|
||||
fakeConfig.AuthInfos["additional-auth"] = clientcmdapi.NewAuthInfo()
|
||||
fakeConfig.Contexts["fake-context"] = clientcmdapi.NewContext()
|
||||
fakeConfig.Contexts["fake-context"].Cluster = "fake"
|
||||
fakeConfig.Contexts["fake-context"].AuthInfo = "fake"
|
||||
fakeConfig.Contexts["additional-context"] = clientcmdapi.NewContext()
|
||||
fakeConfig.Contexts["additional-context"].Cluster = "additional-cluster"
|
||||
fakeConfig.Contexts["additional-context"].AuthInfo = "additional-auth"
|
||||
fakeConfig.CurrentContext = "fake-context"
|
||||
return fakeConfig
|
||||
}
|
||||
52
internal/test/mcp.go
Normal file
52
internal/test/mcp.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/mark3labs/mcp-go/client"
|
||||
"github.com/mark3labs/mcp-go/mcp"
|
||||
"github.com/mark3labs/mcp-go/server"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type McpClient struct {
|
||||
ctx context.Context
|
||||
testServer *httptest.Server
|
||||
*client.Client
|
||||
}
|
||||
|
||||
func NewMcpClient(t *testing.T, mcpHttpServer *server.StreamableHTTPServer) *McpClient {
|
||||
require.NotNil(t, mcpHttpServer, "McpHttpServer must be provided")
|
||||
var err error
|
||||
ret := &McpClient{ctx: t.Context()}
|
||||
ret.testServer = httptest.NewServer(mcpHttpServer)
|
||||
ret.Client, err = client.NewStreamableHttpClient(ret.testServer.URL + "/mcp")
|
||||
require.NoError(t, err, "Expected no error creating MCP client")
|
||||
err = ret.Start(t.Context())
|
||||
require.NoError(t, err, "Expected no error starting MCP client")
|
||||
initRequest := mcp.InitializeRequest{}
|
||||
initRequest.Params.ProtocolVersion = mcp.LATEST_PROTOCOL_VERSION
|
||||
initRequest.Params.ClientInfo = mcp.Implementation{Name: "test", Version: "1.33.7"}
|
||||
_, err = ret.Initialize(t.Context(), initRequest)
|
||||
require.NoError(t, err, "Expected no error initializing MCP client")
|
||||
return ret
|
||||
}
|
||||
|
||||
func (m *McpClient) Close() {
|
||||
if m.Client != nil {
|
||||
_ = m.Client.Close()
|
||||
}
|
||||
if m.testServer != nil {
|
||||
m.testServer.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// CallTool helper function to call a tool by name with arguments
|
||||
func (m *McpClient) CallTool(name string, args map[string]interface{}) (*mcp.CallToolResult, error) {
|
||||
callToolRequest := mcp.CallToolRequest{}
|
||||
callToolRequest.Params.Name = name
|
||||
callToolRequest.Params.Arguments = args
|
||||
return m.Client.CallTool(m.ctx, callToolRequest)
|
||||
}
|
||||
@@ -6,7 +6,10 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
@@ -14,6 +17,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/httpstream"
|
||||
"k8s.io/apimachinery/pkg/util/httpstream/spdy"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/client-go/tools/clientcmd/api"
|
||||
)
|
||||
|
||||
@@ -46,7 +50,9 @@ func NewMockServer() *MockServer {
|
||||
}
|
||||
|
||||
func (m *MockServer) Close() {
|
||||
m.server.Close()
|
||||
if m.server != nil {
|
||||
m.server.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MockServer) Handle(handler http.Handler) {
|
||||
@@ -57,21 +63,22 @@ func (m *MockServer) Config() *rest.Config {
|
||||
return m.config
|
||||
}
|
||||
|
||||
func (m *MockServer) KubeConfig() *api.Config {
|
||||
fakeConfig := api.NewConfig()
|
||||
fakeConfig.Clusters["fake"] = api.NewCluster()
|
||||
func (m *MockServer) Kubeconfig() *api.Config {
|
||||
fakeConfig := KubeConfigFake()
|
||||
fakeConfig.Clusters["fake"].Server = m.config.Host
|
||||
fakeConfig.Clusters["fake"].CertificateAuthorityData = m.config.CAData
|
||||
fakeConfig.AuthInfos["fake"] = api.NewAuthInfo()
|
||||
fakeConfig.AuthInfos["fake"].ClientKeyData = m.config.KeyData
|
||||
fakeConfig.AuthInfos["fake"].ClientCertificateData = m.config.CertData
|
||||
fakeConfig.Contexts["fake-context"] = api.NewContext()
|
||||
fakeConfig.Contexts["fake-context"].Cluster = "fake"
|
||||
fakeConfig.Contexts["fake-context"].AuthInfo = "fake"
|
||||
fakeConfig.CurrentContext = "fake-context"
|
||||
return fakeConfig
|
||||
}
|
||||
|
||||
func (m *MockServer) KubeconfigFile(t *testing.T) string {
|
||||
kubeconfig := filepath.Join(t.TempDir(), "config")
|
||||
err := clientcmd.WriteToFile(*m.Kubeconfig(), kubeconfig)
|
||||
require.NoError(t, err, "Expected no error writing kubeconfig file")
|
||||
return kubeconfig
|
||||
}
|
||||
|
||||
func WriteObject(w http.ResponseWriter, obj runtime.Object) {
|
||||
w.Header().Set("Content-Type", runtime.ContentTypeJSON)
|
||||
if err := json.NewEncoder(w).Encode(obj); err != nil {
|
||||
@@ -170,3 +177,38 @@ WaitForStreams:
|
||||
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
type InOpenShiftHandler struct {
|
||||
}
|
||||
|
||||
var _ http.Handler = (*InOpenShiftHandler)(nil)
|
||||
|
||||
func (h *InOpenShiftHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
// Request Performed by DiscoveryClient to Kube API (Get API Groups legacy -core-)
|
||||
if req.URL.Path == "/api" {
|
||||
_, _ = w.Write([]byte(`{"kind":"APIVersions","versions":[],"serverAddressByClientCIDRs":[{"clientCIDR":"0.0.0.0/0"}]}`))
|
||||
return
|
||||
}
|
||||
// Request Performed by DiscoveryClient to Kube API (Get API Groups)
|
||||
if req.URL.Path == "/apis" {
|
||||
_, _ = w.Write([]byte(`{
|
||||
"kind":"APIGroupList",
|
||||
"groups":[{
|
||||
"name":"project.openshift.io",
|
||||
"versions":[{"groupVersion":"project.openshift.io/v1","version":"v1"}],
|
||||
"preferredVersion":{"groupVersion":"project.openshift.io/v1","version":"v1"}
|
||||
}]}`))
|
||||
return
|
||||
}
|
||||
if req.URL.Path == "/apis/project.openshift.io/v1" {
|
||||
_, _ = w.Write([]byte(`{
|
||||
"kind":"APIResourceList",
|
||||
"apiVersion":"v1",
|
||||
"groupVersion":"project.openshift.io/v1",
|
||||
"resources":[
|
||||
{"name":"projects","singularName":"","namespaced":false,"kind":"Project","verbs":["create","delete","get","list","patch","update","watch"],"shortNames":["pr"]}
|
||||
]}`))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user