@@ -3,177 +3,151 @@ package mcp
33import  (
44	"testing" 
55
6- 	"github.com/containers/kubernetes-mcp-server/pkg/kubernetes" 
76	"github.com/mark3labs/mcp-go/mcp" 
7+ 	"github.com/stretchr/testify/suite" 
88	"k8s.io/client-go/rest" 
99	v1 "k8s.io/client-go/tools/clientcmd/api/v1" 
1010	"sigs.k8s.io/yaml" 
11+ 
12+ 	"github.com/containers/kubernetes-mcp-server/internal/test" 
13+ 	"github.com/containers/kubernetes-mcp-server/pkg/config" 
14+ 	"github.com/containers/kubernetes-mcp-server/pkg/kubernetes" 
1115)
1216
13- func  TestConfigurationView (t  * testing.T ) {
14- 	testCase (t , func (c  * mcpContext ) {
15- 		toolResult , err  :=  c .callTool ("configuration_view" , map [string ]interface {}{})
16- 		t .Run ("configuration_view returns configuration" , func (t  * testing.T ) {
17- 			if  err  !=  nil  {
18- 				t .Fatalf ("call tool failed %v" , err )
19- 			}
20- 		})
17+ type  ConfigurationSuite  struct  {
18+ 	suite.Suite 
19+ 	* test.McpClient 
20+ 	mcpServer  * Server 
21+ 	Cfg        * config.StaticConfig 
22+ }
23+ 
24+ func  (s  * ConfigurationSuite ) SetupTest () {
25+ 	s .Cfg  =  config .Default ()
26+ }
27+ 
28+ func  (s  * ConfigurationSuite ) TearDownTest () {
29+ 	if  s .McpClient  !=  nil  {
30+ 		s .McpClient .Close ()
31+ 	}
32+ 	if  s .mcpServer  !=  nil  {
33+ 		s .mcpServer .Close ()
34+ 	}
35+ }
36+ 
37+ func  (s  * ConfigurationSuite ) InitMcpClient () {
38+ 	var  err  error 
39+ 	s .mcpServer , err  =  NewServer (Configuration {StaticConfig : s .Cfg })
40+ 	s .Require ().NoError (err , "Expected no error creating MCP server" )
41+ 	s .McpClient  =  test .NewMcpClient (s .T (), s .mcpServer .ServeHTTP (nil ))
42+ }
43+ 
44+ func  (s  * ConfigurationSuite ) TestConfigurationView () {
45+ 	// Out of cluster requires kubeconfig 
46+ 	mockServer  :=  test .NewMockServer ()
47+ 	s .T ().Cleanup (mockServer .Close )
48+ 	s .Cfg .KubeConfig  =  mockServer .KubeconfigFile (s .T ())
49+ 	s .InitMcpClient ()
50+ 	s .Run ("configuration_view" , func () {
51+ 		toolResult , err  :=  s .CallTool ("configuration_view" , map [string ]interface {}{})
52+ 		s .Run ("returns configuration" , func () {
53+ 			s .Nilf (err , "call tool failed %v" , err )
54+ 		})
55+ 		s .Require ().NotNil (toolResult , "Expected tool result from call" )
2156		var  decoded  * v1.Config 
2257		err  =  yaml .Unmarshal ([]byte (toolResult .Content [0 ].(mcp.TextContent ).Text ), & decoded )
23- 		t .Run ("configuration_view has yaml content" , func (t  * testing.T ) {
24- 			if  err  !=  nil  {
25- 				t .Fatalf ("invalid tool result content %v" , err )
26- 			}
27- 		})
28- 		t .Run ("configuration_view returns current-context" , func (t  * testing.T ) {
29- 			if  decoded .CurrentContext  !=  "fake-context"  {
30- 				t .Errorf ("fake-context not found: %v" , decoded .CurrentContext )
31- 			}
32- 		})
33- 		t .Run ("configuration_view returns context info" , func (t  * testing.T ) {
34- 			if  len (decoded .Contexts ) !=  1  {
35- 				t .Errorf ("invalid context count, expected 1, got %v" , len (decoded .Contexts ))
36- 			}
37- 			if  decoded .Contexts [0 ].Name  !=  "fake-context"  {
38- 				t .Errorf ("fake-context not found: %v" , decoded .Contexts )
39- 			}
40- 			if  decoded .Contexts [0 ].Context .Cluster  !=  "fake"  {
41- 				t .Errorf ("fake-cluster not found: %v" , decoded .Contexts )
42- 			}
43- 			if  decoded .Contexts [0 ].Context .AuthInfo  !=  "fake"  {
44- 				t .Errorf ("fake-auth not found: %v" , decoded .Contexts )
45- 			}
46- 		})
47- 		t .Run ("configuration_view returns cluster info" , func (t  * testing.T ) {
48- 			if  len (decoded .Clusters ) !=  1  {
49- 				t .Errorf ("invalid cluster count, expected 1, got %v" , len (decoded .Clusters ))
50- 			}
51- 			if  decoded .Clusters [0 ].Name  !=  "fake"  {
52- 				t .Errorf ("fake-cluster not found: %v" , decoded .Clusters )
53- 			}
54- 			if  decoded .Clusters [0 ].Cluster .Server  !=  "https://127.0.0.1:6443"  {
55- 				t .Errorf ("fake-server not found: %v" , decoded .Clusters )
56- 			}
57- 		})
58- 		t .Run ("configuration_view returns auth info" , func (t  * testing.T ) {
59- 			if  len (decoded .AuthInfos ) !=  1  {
60- 				t .Errorf ("invalid auth info count, expected 1, got %v" , len (decoded .AuthInfos ))
61- 			}
62- 			if  decoded .AuthInfos [0 ].Name  !=  "fake"  {
63- 				t .Errorf ("fake-auth not found: %v" , decoded .AuthInfos )
64- 			}
65- 		})
66- 		toolResult , err  =  c .callTool ("configuration_view" , map [string ]interface {}{
58+ 		s .Run ("has yaml content" , func () {
59+ 			s .Nilf (err , "invalid tool result content %v" , err )
60+ 		})
61+ 		s .Run ("returns current-context" , func () {
62+ 			s .Equalf ("fake-context" , decoded .CurrentContext , "fake-context not found: %v" , decoded .CurrentContext )
63+ 		})
64+ 		s .Run ("returns context info" , func () {
65+ 			s .Lenf (decoded .Contexts , 1 , "invalid context count, expected 1, got %v" , len (decoded .Contexts ))
66+ 			s .Equalf ("fake-context" , decoded .Contexts [0 ].Name , "fake-context not found: %v" , decoded .Contexts )
67+ 			s .Equalf ("fake" , decoded .Contexts [0 ].Context .Cluster , "fake-cluster not found: %v" , decoded .Contexts )
68+ 			s .Equalf ("fake" , decoded .Contexts [0 ].Context .AuthInfo , "fake-auth not found: %v" , decoded .Contexts )
69+ 		})
70+ 		s .Run ("returns cluster info" , func () {
71+ 			s .Lenf (decoded .Clusters , 1 , "invalid cluster count, expected 1, got %v" , len (decoded .Clusters ))
72+ 			s .Equalf ("fake" , decoded .Clusters [0 ].Name , "fake-cluster not found: %v" , decoded .Clusters )
73+ 			s .Regexpf (`^https?://(127\.0\.0\.1|localhost):\d{1,5}$` , decoded .Clusters [0 ].Cluster .Server , "fake-server not found: %v" , decoded .Clusters )
74+ 		})
75+ 		s .Run ("returns auth info" , func () {
76+ 			s .Lenf (decoded .AuthInfos , 1 , "invalid auth info count, expected 1, got %v" , len (decoded .AuthInfos ))
77+ 			s .Equalf ("fake" , decoded .AuthInfos [0 ].Name , "fake-auth not found: %v" , decoded .AuthInfos )
78+ 		})
79+ 	})
80+ 	s .Run ("configuration_view(minified=false)" , func () {
81+ 		toolResult , err  :=  s .CallTool ("configuration_view" , map [string ]interface {}{
6782			"minified" : false ,
6883		})
69- 		t .Run ("configuration_view with minified=false returns configuration" , func (t  * testing.T ) {
70- 			if  err  !=  nil  {
71- 				t .Fatalf ("call tool failed %v" , err )
72- 			}
84+ 		s .Run ("returns configuration" , func () {
85+ 			s .Nilf (err , "call tool failed %v" , err )
7386		})
87+ 		var  decoded  * v1.Config 
7488		err  =  yaml .Unmarshal ([]byte (toolResult .Content [0 ].(mcp.TextContent ).Text ), & decoded )
75- 		t .Run ("configuration_view with minified=false has yaml content" , func (t  * testing.T ) {
76- 			if  err  !=  nil  {
77- 				t .Fatalf ("invalid tool result content %v" , err )
78- 			}
79- 		})
80- 		t .Run ("configuration_view with minified=false returns additional context info" , func (t  * testing.T ) {
81- 			if  len (decoded .Contexts ) !=  2  {
82- 				t .Fatalf ("invalid context count, expected2, got %v" , len (decoded .Contexts ))
83- 			}
84- 			if  decoded .Contexts [0 ].Name  !=  "additional-context"  {
85- 				t .Errorf ("additional-context not found: %v" , decoded .Contexts )
86- 			}
87- 			if  decoded .Contexts [0 ].Context .Cluster  !=  "additional-cluster"  {
88- 				t .Errorf ("additional-cluster not found: %v" , decoded .Contexts )
89- 			}
90- 			if  decoded .Contexts [0 ].Context .AuthInfo  !=  "additional-auth"  {
91- 				t .Errorf ("additional-auth not found: %v" , decoded .Contexts )
92- 			}
93- 			if  decoded .Contexts [1 ].Name  !=  "fake-context"  {
94- 				t .Errorf ("fake-context not found: %v" , decoded .Contexts )
95- 			}
96- 		})
97- 		t .Run ("configuration_view with minified=false returns cluster info" , func (t  * testing.T ) {
98- 			if  len (decoded .Clusters ) !=  2  {
99- 				t .Errorf ("invalid cluster count, expected 2, got %v" , len (decoded .Clusters ))
100- 			}
101- 			if  decoded .Clusters [0 ].Name  !=  "additional-cluster"  {
102- 				t .Errorf ("additional-cluster not found: %v" , decoded .Clusters )
103- 			}
104- 		})
105- 		t .Run ("configuration_view with minified=false returns auth info" , func (t  * testing.T ) {
106- 			if  len (decoded .AuthInfos ) !=  2  {
107- 				t .Errorf ("invalid auth info count, expected 2, got %v" , len (decoded .AuthInfos ))
108- 			}
109- 			if  decoded .AuthInfos [0 ].Name  !=  "additional-auth"  {
110- 				t .Errorf ("additional-auth not found: %v" , decoded .AuthInfos )
111- 			}
89+ 		s .Run ("has yaml content" , func () {
90+ 			s .Nilf (err , "invalid tool result content %v" , err )
91+ 		})
92+ 		s .Run ("returns additional context info" , func () {
93+ 			s .Lenf (decoded .Contexts , 2 , "invalid context count, expected 2, got %v" , len (decoded .Contexts ))
94+ 			s .Equalf ("additional-context" , decoded .Contexts [0 ].Name , "additional-context not found: %v" , decoded .Contexts )
95+ 			s .Equalf ("additional-cluster" , decoded .Contexts [0 ].Context .Cluster , "additional-cluster not found: %v" , decoded .Contexts )
96+ 			s .Equalf ("additional-auth" , decoded .Contexts [0 ].Context .AuthInfo , "additional-auth not found: %v" , decoded .Contexts )
97+ 			s .Equalf ("fake-context" , decoded .Contexts [1 ].Name , "fake-context not found: %v" , decoded .Contexts )
98+ 		})
99+ 		s .Run ("returns cluster info" , func () {
100+ 			s .Lenf (decoded .Clusters , 2 , "invalid cluster count, expected 2, got %v" , len (decoded .Clusters ))
101+ 			s .Equalf ("additional-cluster" , decoded .Clusters [0 ].Name , "additional-cluster not found: %v" , decoded .Clusters )
102+ 		})
103+ 		s .Run ("configuration_view with minified=false returns auth info" , func () {
104+ 			s .Lenf (decoded .AuthInfos , 2 , "invalid auth info count, expected 2, got %v" , len (decoded .AuthInfos ))
105+ 			s .Equalf ("additional-auth" , decoded .AuthInfos [0 ].Name , "additional-auth not found: %v" , decoded .AuthInfos )
112106		})
113107	})
114108}
115109
116- func  TestConfigurationViewInCluster ( t   * testing. T ) {
110+ func  ( s   * ConfigurationSuite )  TestConfigurationViewInCluster ( ) {
117111	kubernetes .InClusterConfig  =  func () (* rest.Config , error ) {
118112		return  & rest.Config {
119113			Host :        "https://kubernetes.default.svc" ,
120114			BearerToken : "fake-token" ,
121115		}, nil 
122116	}
123- 	defer  func () {
124- 		kubernetes .InClusterConfig  =  rest .InClusterConfig 
125- 	}()
126- 	testCase (t , func (c  * mcpContext ) {
127- 		toolResult , err  :=  c .callTool ("configuration_view" , map [string ]interface {}{})
128- 		t .Run ("configuration_view returns configuration" , func (t  * testing.T ) {
129- 			if  err  !=  nil  {
130- 				t .Fatalf ("call tool failed %v" , err )
131- 			}
132- 		})
117+ 	s .T ().Cleanup (func () { kubernetes .InClusterConfig  =  rest .InClusterConfig  })
118+ 	s .InitMcpClient ()
119+ 	s .Run ("configuration_view" , func () {
120+ 		toolResult , err  :=  s .CallTool ("configuration_view" , map [string ]interface {}{})
121+ 		s .Run ("returns configuration" , func () {
122+ 			s .Nilf (err , "call tool failed %v" , err )
123+ 		})
124+ 		s .Require ().NotNil (toolResult , "Expected tool result from call" )
133125		var  decoded  * v1.Config 
134126		err  =  yaml .Unmarshal ([]byte (toolResult .Content [0 ].(mcp.TextContent ).Text ), & decoded )
135- 		t .Run ("configuration_view has yaml content" , func (t  * testing.T ) {
136- 			if  err  !=  nil  {
137- 				t .Fatalf ("invalid tool result content %v" , err )
138- 			}
139- 		})
140- 		t .Run ("configuration_view returns current-context" , func (t  * testing.T ) {
141- 			if  decoded .CurrentContext  !=  "context"  {
142- 				t .Fatalf ("context not found: %v" , decoded .CurrentContext )
143- 			}
144- 		})
145- 		t .Run ("configuration_view returns context info" , func (t  * testing.T ) {
146- 			if  len (decoded .Contexts ) !=  1  {
147- 				t .Fatalf ("invalid context count, expected 1, got %v" , len (decoded .Contexts ))
148- 			}
149- 			if  decoded .Contexts [0 ].Name  !=  "context"  {
150- 				t .Fatalf ("context not found: %v" , decoded .Contexts )
151- 			}
152- 			if  decoded .Contexts [0 ].Context .Cluster  !=  "cluster"  {
153- 				t .Fatalf ("cluster not found: %v" , decoded .Contexts )
154- 			}
155- 			if  decoded .Contexts [0 ].Context .AuthInfo  !=  "user"  {
156- 				t .Fatalf ("user not found: %v" , decoded .Contexts )
157- 			}
158- 		})
159- 		t .Run ("configuration_view returns cluster info" , func (t  * testing.T ) {
160- 			if  len (decoded .Clusters ) !=  1  {
161- 				t .Fatalf ("invalid cluster count, expected 1, got %v" , len (decoded .Clusters ))
162- 			}
163- 			if  decoded .Clusters [0 ].Name  !=  "cluster"  {
164- 				t .Fatalf ("cluster not found: %v" , decoded .Clusters )
165- 			}
166- 			if  decoded .Clusters [0 ].Cluster .Server  !=  "https://kubernetes.default.svc"  {
167- 				t .Fatalf ("server not found: %v" , decoded .Clusters )
168- 			}
169- 		})
170- 		t .Run ("configuration_view returns auth info" , func (t  * testing.T ) {
171- 			if  len (decoded .AuthInfos ) !=  1  {
172- 				t .Fatalf ("invalid auth info count, expected 1, got %v" , len (decoded .AuthInfos ))
173- 			}
174- 			if  decoded .AuthInfos [0 ].Name  !=  "user"  {
175- 				t .Fatalf ("user not found: %v" , decoded .AuthInfos )
176- 			}
127+ 		s .Run ("has yaml content" , func () {
128+ 			s .Nilf (err , "invalid tool result content %v" , err )
129+ 		})
130+ 		s .Run ("returns current-context" , func () {
131+ 			s .Equalf ("context" , decoded .CurrentContext , "context not found: %v" , decoded .CurrentContext )
132+ 		})
133+ 		s .Run ("returns context info" , func () {
134+ 			s .Lenf (decoded .Contexts , 1 , "invalid context count, expected 1, got %v" , len (decoded .Contexts ))
135+ 			s .Equalf ("context" , decoded .Contexts [0 ].Name , "context not found: %v" , decoded .Contexts )
136+ 			s .Equalf ("cluster" , decoded .Contexts [0 ].Context .Cluster , "cluster not found: %v" , decoded .Contexts )
137+ 			s .Equalf ("user" , decoded .Contexts [0 ].Context .AuthInfo , "user not found: %v" , decoded .Contexts )
138+ 		})
139+ 		s .Run ("returns cluster info" , func () {
140+ 			s .Lenf (decoded .Clusters , 1 , "invalid cluster count, expected 1, got %v" , len (decoded .Clusters ))
141+ 			s .Equalf ("cluster" , decoded .Clusters [0 ].Name , "cluster not found: %v" , decoded .Clusters )
142+ 			s .Equalf ("https://kubernetes.default.svc" , decoded .Clusters [0 ].Cluster .Server , "server not found: %v" , decoded .Clusters )
143+ 		})
144+ 		s .Run ("returns auth info" , func () {
145+ 			s .Lenf (decoded .AuthInfos , 1 , "invalid auth info count, expected 1, got %v" , len (decoded .AuthInfos ))
146+ 			s .Equalf ("user" , decoded .AuthInfos [0 ].Name , "user not found: %v" , decoded .AuthInfos )
177147		})
178148	})
179149}
150+ 
151+ func  TestConfiguration (t  * testing.T ) {
152+ 	suite .Run (t , new (ConfigurationSuite ))
153+ }
0 commit comments