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:
Marc Nuri
2025-09-17 11:06:17 +02:00
committed by GitHub
parent 48cf204a89
commit d9d35b9834
10 changed files with 788 additions and 108 deletions

View 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
View 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)
}

View File

@@ -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
}
}