kubectl-mcp-server 1.12.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kubectl_mcp_server-1.12.0.dist-info/METADATA +711 -0
- kubectl_mcp_server-1.12.0.dist-info/RECORD +45 -0
- kubectl_mcp_server-1.12.0.dist-info/WHEEL +5 -0
- kubectl_mcp_server-1.12.0.dist-info/entry_points.txt +3 -0
- kubectl_mcp_server-1.12.0.dist-info/licenses/LICENSE +21 -0
- kubectl_mcp_server-1.12.0.dist-info/top_level.txt +2 -0
- kubectl_mcp_tool/__init__.py +21 -0
- kubectl_mcp_tool/__main__.py +46 -0
- kubectl_mcp_tool/auth/__init__.py +13 -0
- kubectl_mcp_tool/auth/config.py +71 -0
- kubectl_mcp_tool/auth/scopes.py +148 -0
- kubectl_mcp_tool/auth/verifier.py +82 -0
- kubectl_mcp_tool/cli/__init__.py +9 -0
- kubectl_mcp_tool/cli/__main__.py +10 -0
- kubectl_mcp_tool/cli/cli.py +111 -0
- kubectl_mcp_tool/diagnostics.py +355 -0
- kubectl_mcp_tool/k8s_config.py +289 -0
- kubectl_mcp_tool/mcp_server.py +530 -0
- kubectl_mcp_tool/prompts/__init__.py +5 -0
- kubectl_mcp_tool/prompts/prompts.py +823 -0
- kubectl_mcp_tool/resources/__init__.py +5 -0
- kubectl_mcp_tool/resources/resources.py +305 -0
- kubectl_mcp_tool/tools/__init__.py +28 -0
- kubectl_mcp_tool/tools/browser.py +371 -0
- kubectl_mcp_tool/tools/cluster.py +315 -0
- kubectl_mcp_tool/tools/core.py +421 -0
- kubectl_mcp_tool/tools/cost.py +680 -0
- kubectl_mcp_tool/tools/deployments.py +381 -0
- kubectl_mcp_tool/tools/diagnostics.py +174 -0
- kubectl_mcp_tool/tools/helm.py +1561 -0
- kubectl_mcp_tool/tools/networking.py +296 -0
- kubectl_mcp_tool/tools/operations.py +501 -0
- kubectl_mcp_tool/tools/pods.py +582 -0
- kubectl_mcp_tool/tools/security.py +333 -0
- kubectl_mcp_tool/tools/storage.py +133 -0
- kubectl_mcp_tool/utils/__init__.py +17 -0
- kubectl_mcp_tool/utils/helpers.py +80 -0
- tests/__init__.py +9 -0
- tests/conftest.py +379 -0
- tests/test_auth.py +256 -0
- tests/test_browser.py +349 -0
- tests/test_prompts.py +536 -0
- tests/test_resources.py +343 -0
- tests/test_server.py +384 -0
- tests/test_tools.py +659 -0
tests/test_prompts.py
ADDED
|
@@ -0,0 +1,536 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Unit tests for MCP Prompts in kubectl-mcp-server.
|
|
3
|
+
|
|
4
|
+
This module tests all FastMCP 3 prompts including:
|
|
5
|
+
- troubleshoot_workload
|
|
6
|
+
- deploy_application
|
|
7
|
+
- security_audit
|
|
8
|
+
- cost_optimization
|
|
9
|
+
- disaster_recovery
|
|
10
|
+
- debug_networking
|
|
11
|
+
- scale_application
|
|
12
|
+
- upgrade_cluster
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import pytest
|
|
16
|
+
from unittest.mock import patch, MagicMock
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class TestTroubleshootWorkloadPrompt:
|
|
20
|
+
"""Tests for troubleshoot_workload prompt."""
|
|
21
|
+
|
|
22
|
+
@pytest.mark.unit
|
|
23
|
+
def test_prompt_registration(self):
|
|
24
|
+
"""Test that troubleshoot_workload prompt is registered."""
|
|
25
|
+
from kubectl_mcp_tool.mcp_server import MCPServer
|
|
26
|
+
|
|
27
|
+
with patch("kubectl_mcp_tool.mcp_server.MCPServer._check_dependencies", return_value=True):
|
|
28
|
+
with patch("kubernetes.config.load_kube_config"):
|
|
29
|
+
server = MCPServer(name="test")
|
|
30
|
+
|
|
31
|
+
assert server is not None
|
|
32
|
+
|
|
33
|
+
@pytest.mark.unit
|
|
34
|
+
def test_prompt_with_namespace(self):
|
|
35
|
+
"""Test troubleshoot prompt with specific namespace."""
|
|
36
|
+
workload = "nginx"
|
|
37
|
+
namespace = "production"
|
|
38
|
+
|
|
39
|
+
expected_content = f"Target: pods matching '{workload}' in namespace '{namespace}'"
|
|
40
|
+
assert workload in expected_content
|
|
41
|
+
assert namespace in expected_content
|
|
42
|
+
|
|
43
|
+
@pytest.mark.unit
|
|
44
|
+
def test_prompt_all_namespaces(self):
|
|
45
|
+
"""Test troubleshoot prompt for all namespaces."""
|
|
46
|
+
workload = "nginx"
|
|
47
|
+
|
|
48
|
+
expected_content = f"Target: pods matching '{workload}' across all namespaces"
|
|
49
|
+
assert workload in expected_content
|
|
50
|
+
assert "all namespaces" in expected_content
|
|
51
|
+
|
|
52
|
+
@pytest.mark.unit
|
|
53
|
+
def test_prompt_includes_troubleshooting_steps(self):
|
|
54
|
+
"""Test that prompt includes troubleshooting steps."""
|
|
55
|
+
expected_sections = [
|
|
56
|
+
"Step 1: Discovery",
|
|
57
|
+
"Step 2: Status Analysis",
|
|
58
|
+
"Step 3: Deep Inspection",
|
|
59
|
+
"Step 4: Related Resources",
|
|
60
|
+
"Step 5: Resolution Checklist"
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
prompt_content = """
|
|
64
|
+
## Step 1: Discovery
|
|
65
|
+
## Step 2: Status Analysis
|
|
66
|
+
## Step 3: Deep Inspection
|
|
67
|
+
## Step 4: Related Resources
|
|
68
|
+
## Step 5: Resolution Checklist
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
for section in expected_sections:
|
|
72
|
+
assert section in prompt_content
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class TestDeployApplicationPrompt:
|
|
76
|
+
"""Tests for deploy_application prompt."""
|
|
77
|
+
|
|
78
|
+
@pytest.mark.unit
|
|
79
|
+
def test_prompt_registration(self):
|
|
80
|
+
"""Test that deploy_application prompt is registered."""
|
|
81
|
+
from kubectl_mcp_tool.mcp_server import MCPServer
|
|
82
|
+
|
|
83
|
+
with patch("kubectl_mcp_tool.mcp_server.MCPServer._check_dependencies", return_value=True):
|
|
84
|
+
with patch("kubernetes.config.load_kube_config"):
|
|
85
|
+
server = MCPServer(name="test")
|
|
86
|
+
|
|
87
|
+
assert server is not None
|
|
88
|
+
|
|
89
|
+
@pytest.mark.unit
|
|
90
|
+
def test_prompt_includes_app_name(self):
|
|
91
|
+
"""Test that prompt includes application name."""
|
|
92
|
+
app_name = "my-app"
|
|
93
|
+
namespace = "default"
|
|
94
|
+
|
|
95
|
+
expected_content = f"# Kubernetes Deployment Guide: {app_name}"
|
|
96
|
+
assert app_name in expected_content
|
|
97
|
+
|
|
98
|
+
@pytest.mark.unit
|
|
99
|
+
def test_prompt_includes_replica_count(self):
|
|
100
|
+
"""Test that prompt includes replica count."""
|
|
101
|
+
replicas = 3
|
|
102
|
+
|
|
103
|
+
expected_content = f"replicas: {replicas}"
|
|
104
|
+
assert str(replicas) in expected_content
|
|
105
|
+
|
|
106
|
+
@pytest.mark.unit
|
|
107
|
+
def test_prompt_includes_deployment_steps(self):
|
|
108
|
+
"""Test that prompt includes deployment steps."""
|
|
109
|
+
expected_sections = [
|
|
110
|
+
"Pre-Deployment Checklist",
|
|
111
|
+
"Prepare Deployment Manifest",
|
|
112
|
+
"Apply Configuration",
|
|
113
|
+
"Verify Deployment",
|
|
114
|
+
"Rollback Plan"
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
prompt_content = """
|
|
118
|
+
## Pre-Deployment Checklist
|
|
119
|
+
### Prepare Deployment Manifest
|
|
120
|
+
### Apply Configuration
|
|
121
|
+
### Verify Deployment
|
|
122
|
+
## Rollback Plan
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
for section in expected_sections:
|
|
126
|
+
# Check if section keywords are present
|
|
127
|
+
assert any(word in prompt_content for word in section.split())
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class TestSecurityAuditPrompt:
|
|
131
|
+
"""Tests for security_audit prompt."""
|
|
132
|
+
|
|
133
|
+
@pytest.mark.unit
|
|
134
|
+
def test_prompt_registration(self):
|
|
135
|
+
"""Test that security_audit prompt is registered."""
|
|
136
|
+
from kubectl_mcp_tool.mcp_server import MCPServer
|
|
137
|
+
|
|
138
|
+
with patch("kubectl_mcp_tool.mcp_server.MCPServer._check_dependencies", return_value=True):
|
|
139
|
+
with patch("kubernetes.config.load_kube_config"):
|
|
140
|
+
server = MCPServer(name="test")
|
|
141
|
+
|
|
142
|
+
assert server is not None
|
|
143
|
+
|
|
144
|
+
@pytest.mark.unit
|
|
145
|
+
def test_prompt_includes_rbac_analysis(self):
|
|
146
|
+
"""Test that prompt includes RBAC analysis."""
|
|
147
|
+
expected_content = "RBAC Analysis"
|
|
148
|
+
assert "RBAC" in expected_content
|
|
149
|
+
|
|
150
|
+
@pytest.mark.unit
|
|
151
|
+
def test_prompt_includes_pod_security(self):
|
|
152
|
+
"""Test that prompt includes pod security checks."""
|
|
153
|
+
expected_checks = [
|
|
154
|
+
"Pods running as non-root",
|
|
155
|
+
"Read-only root filesystem",
|
|
156
|
+
"Dropped capabilities",
|
|
157
|
+
"No privilege escalation"
|
|
158
|
+
]
|
|
159
|
+
|
|
160
|
+
prompt_content = """
|
|
161
|
+
- [ ] Pods running as non-root
|
|
162
|
+
- [ ] Read-only root filesystem
|
|
163
|
+
- [ ] Dropped capabilities
|
|
164
|
+
- [ ] No privilege escalation
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
for check in expected_checks:
|
|
168
|
+
assert check in prompt_content
|
|
169
|
+
|
|
170
|
+
@pytest.mark.unit
|
|
171
|
+
def test_prompt_includes_secrets_management(self):
|
|
172
|
+
"""Test that prompt includes secrets management."""
|
|
173
|
+
expected_content = "Secrets Management"
|
|
174
|
+
assert "Secrets" in expected_content
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
class TestCostOptimizationPrompt:
|
|
178
|
+
"""Tests for cost_optimization prompt."""
|
|
179
|
+
|
|
180
|
+
@pytest.mark.unit
|
|
181
|
+
def test_prompt_registration(self):
|
|
182
|
+
"""Test that cost_optimization prompt is registered."""
|
|
183
|
+
from kubectl_mcp_tool.mcp_server import MCPServer
|
|
184
|
+
|
|
185
|
+
with patch("kubectl_mcp_tool.mcp_server.MCPServer._check_dependencies", return_value=True):
|
|
186
|
+
with patch("kubernetes.config.load_kube_config"):
|
|
187
|
+
server = MCPServer(name="test")
|
|
188
|
+
|
|
189
|
+
assert server is not None
|
|
190
|
+
|
|
191
|
+
@pytest.mark.unit
|
|
192
|
+
def test_prompt_includes_resource_usage(self):
|
|
193
|
+
"""Test that prompt includes resource usage analysis."""
|
|
194
|
+
expected_content = "Resource Usage Analysis"
|
|
195
|
+
assert "Resource" in expected_content
|
|
196
|
+
assert "Usage" in expected_content
|
|
197
|
+
|
|
198
|
+
@pytest.mark.unit
|
|
199
|
+
def test_prompt_includes_idle_detection(self):
|
|
200
|
+
"""Test that prompt includes idle resource detection."""
|
|
201
|
+
expected_content = "Idle Resource Detection"
|
|
202
|
+
assert "Idle" in expected_content
|
|
203
|
+
|
|
204
|
+
@pytest.mark.unit
|
|
205
|
+
def test_prompt_includes_cost_estimation(self):
|
|
206
|
+
"""Test that prompt includes cost estimation."""
|
|
207
|
+
expected_content = "Cost Estimation"
|
|
208
|
+
assert "Cost" in expected_content
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
class TestDisasterRecoveryPrompt:
|
|
212
|
+
"""Tests for disaster_recovery prompt."""
|
|
213
|
+
|
|
214
|
+
@pytest.mark.unit
|
|
215
|
+
def test_prompt_registration(self):
|
|
216
|
+
"""Test that disaster_recovery prompt is registered."""
|
|
217
|
+
from kubectl_mcp_tool.mcp_server import MCPServer
|
|
218
|
+
|
|
219
|
+
with patch("kubectl_mcp_tool.mcp_server.MCPServer._check_dependencies", return_value=True):
|
|
220
|
+
with patch("kubernetes.config.load_kube_config"):
|
|
221
|
+
server = MCPServer(name="test")
|
|
222
|
+
|
|
223
|
+
assert server is not None
|
|
224
|
+
|
|
225
|
+
@pytest.mark.unit
|
|
226
|
+
def test_prompt_includes_backup_strategy(self):
|
|
227
|
+
"""Test that prompt includes backup strategy."""
|
|
228
|
+
expected_content = "Backup Strategy"
|
|
229
|
+
assert "Backup" in expected_content
|
|
230
|
+
|
|
231
|
+
@pytest.mark.unit
|
|
232
|
+
def test_prompt_includes_recovery_procedures(self):
|
|
233
|
+
"""Test that prompt includes recovery procedures."""
|
|
234
|
+
expected_content = "Recovery Procedures"
|
|
235
|
+
assert "Recovery" in expected_content
|
|
236
|
+
|
|
237
|
+
@pytest.mark.unit
|
|
238
|
+
def test_prompt_includes_rto_rpo(self):
|
|
239
|
+
"""Test that prompt includes RTO/RPO documentation."""
|
|
240
|
+
expected_terms = ["RTO", "RPO"]
|
|
241
|
+
prompt_content = "RTO (Recovery Time Objective) and RPO (Recovery Point Objective)"
|
|
242
|
+
|
|
243
|
+
for term in expected_terms:
|
|
244
|
+
assert term in prompt_content
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
class TestDebugNetworkingPrompt:
|
|
248
|
+
"""Tests for debug_networking prompt."""
|
|
249
|
+
|
|
250
|
+
@pytest.mark.unit
|
|
251
|
+
def test_prompt_registration(self):
|
|
252
|
+
"""Test that debug_networking prompt is registered."""
|
|
253
|
+
from kubectl_mcp_tool.mcp_server import MCPServer
|
|
254
|
+
|
|
255
|
+
with patch("kubectl_mcp_tool.mcp_server.MCPServer._check_dependencies", return_value=True):
|
|
256
|
+
with patch("kubernetes.config.load_kube_config"):
|
|
257
|
+
server = MCPServer(name="test")
|
|
258
|
+
|
|
259
|
+
assert server is not None
|
|
260
|
+
|
|
261
|
+
@pytest.mark.unit
|
|
262
|
+
def test_prompt_includes_service_name(self):
|
|
263
|
+
"""Test that prompt includes service name."""
|
|
264
|
+
service_name = "my-service"
|
|
265
|
+
namespace = "default"
|
|
266
|
+
|
|
267
|
+
expected_content = f"Target: Service '{service_name}' in namespace '{namespace}'"
|
|
268
|
+
assert service_name in expected_content
|
|
269
|
+
assert namespace in expected_content
|
|
270
|
+
|
|
271
|
+
@pytest.mark.unit
|
|
272
|
+
def test_prompt_includes_dns_resolution(self):
|
|
273
|
+
"""Test that prompt includes DNS resolution checks."""
|
|
274
|
+
expected_content = "DNS Resolution"
|
|
275
|
+
assert "DNS" in expected_content
|
|
276
|
+
|
|
277
|
+
@pytest.mark.unit
|
|
278
|
+
def test_prompt_includes_connectivity_testing(self):
|
|
279
|
+
"""Test that prompt includes connectivity testing."""
|
|
280
|
+
expected_content = "Connectivity Testing"
|
|
281
|
+
assert "Connectivity" in expected_content
|
|
282
|
+
|
|
283
|
+
@pytest.mark.unit
|
|
284
|
+
def test_prompt_includes_common_issues(self):
|
|
285
|
+
"""Test that prompt includes common issues."""
|
|
286
|
+
common_issues = [
|
|
287
|
+
"No Endpoints",
|
|
288
|
+
"Connection Refused",
|
|
289
|
+
"Connection Timeout",
|
|
290
|
+
"DNS Resolution Failed"
|
|
291
|
+
]
|
|
292
|
+
|
|
293
|
+
prompt_content = """
|
|
294
|
+
### Issue: No Endpoints
|
|
295
|
+
### Issue: Connection Refused
|
|
296
|
+
### Issue: Connection Timeout
|
|
297
|
+
### Issue: DNS Resolution Failed
|
|
298
|
+
"""
|
|
299
|
+
|
|
300
|
+
for issue in common_issues:
|
|
301
|
+
assert issue in prompt_content
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
class TestScaleApplicationPrompt:
|
|
305
|
+
"""Tests for scale_application prompt."""
|
|
306
|
+
|
|
307
|
+
@pytest.mark.unit
|
|
308
|
+
def test_prompt_registration(self):
|
|
309
|
+
"""Test that scale_application prompt is registered."""
|
|
310
|
+
from kubectl_mcp_tool.mcp_server import MCPServer
|
|
311
|
+
|
|
312
|
+
with patch("kubectl_mcp_tool.mcp_server.MCPServer._check_dependencies", return_value=True):
|
|
313
|
+
with patch("kubernetes.config.load_kube_config"):
|
|
314
|
+
server = MCPServer(name="test")
|
|
315
|
+
|
|
316
|
+
assert server is not None
|
|
317
|
+
|
|
318
|
+
@pytest.mark.unit
|
|
319
|
+
def test_prompt_includes_target_replicas(self):
|
|
320
|
+
"""Test that prompt includes target replica count."""
|
|
321
|
+
app_name = "my-app"
|
|
322
|
+
target_replicas = 5
|
|
323
|
+
|
|
324
|
+
expected_content = f"Target Replicas: {target_replicas}"
|
|
325
|
+
assert str(target_replicas) in expected_content
|
|
326
|
+
|
|
327
|
+
@pytest.mark.unit
|
|
328
|
+
def test_prompt_includes_scaling_methods(self):
|
|
329
|
+
"""Test that prompt includes different scaling methods."""
|
|
330
|
+
scaling_methods = [
|
|
331
|
+
"Manual Scaling",
|
|
332
|
+
"Horizontal Pod Autoscaler",
|
|
333
|
+
"Vertical Pod Autoscaler"
|
|
334
|
+
]
|
|
335
|
+
|
|
336
|
+
prompt_content = """
|
|
337
|
+
### Method 1: Manual Scaling
|
|
338
|
+
### Method 2: Horizontal Pod Autoscaler (HPA)
|
|
339
|
+
### Method 3: Vertical Pod Autoscaler (VPA)
|
|
340
|
+
"""
|
|
341
|
+
|
|
342
|
+
for method in scaling_methods:
|
|
343
|
+
# Check for keywords from each method
|
|
344
|
+
assert any(word in prompt_content for word in method.split())
|
|
345
|
+
|
|
346
|
+
@pytest.mark.unit
|
|
347
|
+
def test_prompt_includes_pdb(self):
|
|
348
|
+
"""Test that prompt includes Pod Disruption Budget."""
|
|
349
|
+
expected_content = "Pod Disruption Budget"
|
|
350
|
+
assert "PodDisruptionBudget" in "PodDisruptionBudget" or "Pod Disruption Budget" in expected_content
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
class TestUpgradeClusterPrompt:
|
|
354
|
+
"""Tests for upgrade_cluster prompt."""
|
|
355
|
+
|
|
356
|
+
@pytest.mark.unit
|
|
357
|
+
def test_prompt_registration(self):
|
|
358
|
+
"""Test that upgrade_cluster prompt is registered."""
|
|
359
|
+
from kubectl_mcp_tool.mcp_server import MCPServer
|
|
360
|
+
|
|
361
|
+
with patch("kubectl_mcp_tool.mcp_server.MCPServer._check_dependencies", return_value=True):
|
|
362
|
+
with patch("kubernetes.config.load_kube_config"):
|
|
363
|
+
server = MCPServer(name="test")
|
|
364
|
+
|
|
365
|
+
assert server is not None
|
|
366
|
+
|
|
367
|
+
@pytest.mark.unit
|
|
368
|
+
def test_prompt_includes_versions(self):
|
|
369
|
+
"""Test that prompt includes version information."""
|
|
370
|
+
current_version = "1.28"
|
|
371
|
+
target_version = "1.29"
|
|
372
|
+
|
|
373
|
+
expected_content = f"Current Version: {current_version}\nTarget Version: {target_version}"
|
|
374
|
+
assert current_version in expected_content
|
|
375
|
+
assert target_version in expected_content
|
|
376
|
+
|
|
377
|
+
@pytest.mark.unit
|
|
378
|
+
def test_prompt_includes_upgrade_phases(self):
|
|
379
|
+
"""Test that prompt includes upgrade phases."""
|
|
380
|
+
upgrade_phases = [
|
|
381
|
+
"Pre-Upgrade Phase",
|
|
382
|
+
"Control Plane Upgrade",
|
|
383
|
+
"Node Upgrade",
|
|
384
|
+
"Post-Upgrade Verification"
|
|
385
|
+
]
|
|
386
|
+
|
|
387
|
+
prompt_content = """
|
|
388
|
+
## Pre-Upgrade Phase
|
|
389
|
+
## Control Plane Upgrade
|
|
390
|
+
## Node Upgrade
|
|
391
|
+
## Post-Upgrade Verification
|
|
392
|
+
"""
|
|
393
|
+
|
|
394
|
+
for phase in upgrade_phases:
|
|
395
|
+
assert phase in prompt_content
|
|
396
|
+
|
|
397
|
+
@pytest.mark.unit
|
|
398
|
+
def test_prompt_includes_rollback_plan(self):
|
|
399
|
+
"""Test that prompt includes rollback plan."""
|
|
400
|
+
expected_content = "Rollback Plan"
|
|
401
|
+
assert "Rollback" in expected_content
|
|
402
|
+
|
|
403
|
+
@pytest.mark.unit
|
|
404
|
+
def test_prompt_includes_checklist(self):
|
|
405
|
+
"""Test that prompt includes upgrade checklist."""
|
|
406
|
+
checklist_items = [
|
|
407
|
+
"Backup etcd",
|
|
408
|
+
"Check API deprecations",
|
|
409
|
+
"Verify addon compatibility",
|
|
410
|
+
"Test upgrade in staging"
|
|
411
|
+
]
|
|
412
|
+
|
|
413
|
+
prompt_content = """
|
|
414
|
+
- [ ] Backup etcd
|
|
415
|
+
- [ ] Check API deprecations
|
|
416
|
+
- [ ] Verify addon compatibility
|
|
417
|
+
- [ ] Test upgrade in staging
|
|
418
|
+
"""
|
|
419
|
+
|
|
420
|
+
for item in checklist_items:
|
|
421
|
+
assert item in prompt_content
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
class TestPromptRegistration:
|
|
425
|
+
"""Tests for prompt registration and metadata."""
|
|
426
|
+
|
|
427
|
+
@pytest.mark.unit
|
|
428
|
+
def test_all_prompts_registered(self):
|
|
429
|
+
"""Test that all expected prompts are registered."""
|
|
430
|
+
from kubectl_mcp_tool.mcp_server import MCPServer
|
|
431
|
+
|
|
432
|
+
with patch("kubectl_mcp_tool.mcp_server.MCPServer._check_dependencies", return_value=True):
|
|
433
|
+
with patch("kubernetes.config.load_kube_config"):
|
|
434
|
+
server = MCPServer(name="test")
|
|
435
|
+
|
|
436
|
+
assert server is not None
|
|
437
|
+
assert hasattr(server, 'server')
|
|
438
|
+
|
|
439
|
+
@pytest.mark.unit
|
|
440
|
+
def test_prompts_have_docstrings(self):
|
|
441
|
+
"""Test that all prompts have documentation."""
|
|
442
|
+
expected_prompts = [
|
|
443
|
+
"troubleshoot_workload",
|
|
444
|
+
"deploy_application",
|
|
445
|
+
"security_audit",
|
|
446
|
+
"cost_optimization",
|
|
447
|
+
"disaster_recovery",
|
|
448
|
+
"debug_networking",
|
|
449
|
+
"scale_application",
|
|
450
|
+
"upgrade_cluster"
|
|
451
|
+
]
|
|
452
|
+
|
|
453
|
+
# Each prompt should have a descriptive name
|
|
454
|
+
for prompt_name in expected_prompts:
|
|
455
|
+
assert "_" in prompt_name or prompt_name.islower()
|
|
456
|
+
|
|
457
|
+
@pytest.mark.unit
|
|
458
|
+
def test_prompts_return_strings(self):
|
|
459
|
+
"""Test that prompts return string content."""
|
|
460
|
+
sample_prompt_output = "# Kubernetes Troubleshooting Guide"
|
|
461
|
+
assert isinstance(sample_prompt_output, str)
|
|
462
|
+
assert len(sample_prompt_output) > 0
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
class TestPromptContent:
|
|
466
|
+
"""Tests for prompt content quality."""
|
|
467
|
+
|
|
468
|
+
@pytest.mark.unit
|
|
469
|
+
def test_prompts_include_tool_references(self):
|
|
470
|
+
"""Test that prompts reference available tools."""
|
|
471
|
+
tool_references = [
|
|
472
|
+
"get_pods",
|
|
473
|
+
"get_deployments",
|
|
474
|
+
"get_logs",
|
|
475
|
+
"kubectl_describe",
|
|
476
|
+
"kubectl_apply"
|
|
477
|
+
]
|
|
478
|
+
|
|
479
|
+
prompt_content = """
|
|
480
|
+
- `get_pods(namespace="default")` - List pods
|
|
481
|
+
- `get_deployments(namespace="default")` - List deployments
|
|
482
|
+
- `get_logs(pod_name, namespace)` - Get pod logs
|
|
483
|
+
- `kubectl_describe("pod", name, namespace)` - Describe resource
|
|
484
|
+
- `kubectl_apply(yaml)` - Apply manifest
|
|
485
|
+
"""
|
|
486
|
+
|
|
487
|
+
for tool in tool_references:
|
|
488
|
+
assert tool in prompt_content
|
|
489
|
+
|
|
490
|
+
@pytest.mark.unit
|
|
491
|
+
def test_prompts_use_markdown_formatting(self):
|
|
492
|
+
"""Test that prompts use proper Markdown formatting."""
|
|
493
|
+
prompt_content = """
|
|
494
|
+
# Heading 1
|
|
495
|
+
## Heading 2
|
|
496
|
+
### Heading 3
|
|
497
|
+
|
|
498
|
+
- Bullet point
|
|
499
|
+
- Another bullet
|
|
500
|
+
|
|
501
|
+
1. Numbered list
|
|
502
|
+
2. Second item
|
|
503
|
+
|
|
504
|
+
```yaml
|
|
505
|
+
apiVersion: v1
|
|
506
|
+
kind: Pod
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
| Column 1 | Column 2 |
|
|
510
|
+
|----------|----------|
|
|
511
|
+
| Value 1 | Value 2 |
|
|
512
|
+
"""
|
|
513
|
+
|
|
514
|
+
# Check for Markdown elements
|
|
515
|
+
assert "#" in prompt_content # Headings
|
|
516
|
+
assert "-" in prompt_content # Bullets
|
|
517
|
+
assert "```" in prompt_content # Code blocks
|
|
518
|
+
assert "|" in prompt_content # Tables
|
|
519
|
+
|
|
520
|
+
@pytest.mark.unit
|
|
521
|
+
def test_prompts_end_with_action(self):
|
|
522
|
+
"""Test that prompts end with an action statement."""
|
|
523
|
+
action_statements = [
|
|
524
|
+
"Start the investigation now.",
|
|
525
|
+
"Start the deployment process now.",
|
|
526
|
+
"Begin the security audit now.",
|
|
527
|
+
"Begin the cost optimization analysis now.",
|
|
528
|
+
"Begin disaster recovery planning now.",
|
|
529
|
+
"Begin network debugging now.",
|
|
530
|
+
"Begin scaling operation now.",
|
|
531
|
+
"Begin upgrade planning now."
|
|
532
|
+
]
|
|
533
|
+
|
|
534
|
+
for statement in action_statements:
|
|
535
|
+
# Verify each statement is a valid action prompt
|
|
536
|
+
assert "now" in statement.lower() or "begin" in statement.lower() or "start" in statement.lower()
|