Skip to content

Commit 60313c4

Browse files
committed
Adding Go Templates specific tests
1 parent ad61d86 commit 60313c4

5 files changed

Lines changed: 147 additions & 8 deletions

File tree

pkg/mcp/resources_test.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,113 @@ func (s *ResourcesSuite) TestResourcesScaleDenied() {
10291029
})
10301030
}
10311031

1032+
func (s *ResourcesSuite) TestResourcesListGoTemplate() {
1033+
s.InitMcpClient()
1034+
s.Run("resources_list with gotemplate extracts names", func() {
1035+
result, err := s.CallTool("resources_list", map[string]interface{}{
1036+
"apiVersion": "v1",
1037+
"kind": "Pod",
1038+
"namespace": "default",
1039+
"gotemplate": "{{range .items}}{{.metadata.name}}\n{{end}}",
1040+
})
1041+
s.Nilf(err, "call tool failed %v", err)
1042+
s.Falsef(result.IsError, "call tool failed: %v", result.Content)
1043+
content := result.Content[0].(*mcp.TextContent).Text
1044+
s.Contains(content, "a-pod-in-default")
1045+
})
1046+
s.Run("resources_list with gotemplate extracts namespace and name", func() {
1047+
result, err := s.CallTool("resources_list", map[string]interface{}{
1048+
"apiVersion": "v1",
1049+
"kind": "Pod",
1050+
"namespace": "default",
1051+
"gotemplate": "{{range .items}}{{.metadata.namespace}}/{{.metadata.name}}\n{{end}}",
1052+
})
1053+
s.Nilf(err, "call tool failed %v", err)
1054+
s.Falsef(result.IsError, "call tool failed: %v", result.Content)
1055+
content := result.Content[0].(*mcp.TextContent).Text
1056+
s.Contains(content, "default/a-pod-in-default")
1057+
})
1058+
s.Run("resources_list with invalid gotemplate returns error", func() {
1059+
result, _ := s.CallTool("resources_list", map[string]interface{}{
1060+
"apiVersion": "v1",
1061+
"kind": "Pod",
1062+
"namespace": "default",
1063+
"gotemplate": "{{invalid",
1064+
})
1065+
s.Truef(result.IsError, "call tool should fail for invalid template")
1066+
s.Contains(result.Content[0].(*mcp.TextContent).Text, "invalid go template expression")
1067+
})
1068+
s.Run("resources_list with gotemplate on empty list returns no output", func() {
1069+
result, err := s.CallTool("resources_list", map[string]interface{}{
1070+
"apiVersion": "v1",
1071+
"kind": "Pod",
1072+
"namespace": "default",
1073+
"labelSelector": "nonexistent-label=nonexistent-value",
1074+
"gotemplate": "{{range .items}}{{.metadata.name}}\n{{end}}",
1075+
})
1076+
s.Nilf(err, "call tool failed %v", err)
1077+
s.Falsef(result.IsError, "call tool should not fail: %v", result.Content)
1078+
content := result.Content[0].(*mcp.TextContent).Text
1079+
s.Equal("(no output from go template)", content)
1080+
})
1081+
}
1082+
1083+
func (s *ResourcesSuite) TestResourcesListGoTemplateInTableMode() {
1084+
s.Cfg.ListOutput = "table"
1085+
s.InitMcpClient()
1086+
s.Run("resources_list with gotemplate works even when list output is table", func() {
1087+
result, err := s.CallTool("resources_list", map[string]interface{}{
1088+
"apiVersion": "v1",
1089+
"kind": "Pod",
1090+
"namespace": "default",
1091+
"gotemplate": "{{range .items}}{{.metadata.name}}\n{{end}}",
1092+
})
1093+
s.Nilf(err, "call tool failed %v", err)
1094+
s.Falsef(result.IsError, "call tool failed: %v", result.Content)
1095+
content := result.Content[0].(*mcp.TextContent).Text
1096+
s.Contains(content, "a-pod-in-default")
1097+
})
1098+
}
1099+
1100+
func (s *ResourcesSuite) TestResourcesGetGoTemplate() {
1101+
s.InitMcpClient()
1102+
s.Run("resources_get with gotemplate extracts specific field", func() {
1103+
result, err := s.CallTool("resources_get", map[string]interface{}{
1104+
"apiVersion": "v1",
1105+
"kind": "Namespace",
1106+
"name": "default",
1107+
"gotemplate": "{{.metadata.name}}",
1108+
})
1109+
s.Nilf(err, "call tool failed %v", err)
1110+
s.Falsef(result.IsError, "call tool failed: %v", result.Content)
1111+
content := result.Content[0].(*mcp.TextContent).Text
1112+
s.Equal("default", content)
1113+
})
1114+
s.Run("resources_get with gotemplate extracts nested fields", func() {
1115+
result, err := s.CallTool("resources_get", map[string]interface{}{
1116+
"apiVersion": "v1",
1117+
"kind": "Pod",
1118+
"namespace": "default",
1119+
"name": "a-pod-in-default",
1120+
"gotemplate": "{{.kind}}/{{.metadata.name}}",
1121+
})
1122+
s.Nilf(err, "call tool failed %v", err)
1123+
s.Falsef(result.IsError, "call tool failed: %v", result.Content)
1124+
content := result.Content[0].(*mcp.TextContent).Text
1125+
s.Equal("Pod/a-pod-in-default", content)
1126+
})
1127+
s.Run("resources_get with invalid gotemplate returns error", func() {
1128+
result, _ := s.CallTool("resources_get", map[string]interface{}{
1129+
"apiVersion": "v1",
1130+
"kind": "Namespace",
1131+
"name": "default",
1132+
"gotemplate": "{{invalid",
1133+
})
1134+
s.Truef(result.IsError, "call tool should fail for invalid template")
1135+
s.Contains(result.Content[0].(*mcp.TextContent).Text, "invalid go template expression")
1136+
})
1137+
}
1138+
10321139
func TestResources(t *testing.T) {
10331140
suite.Run(t, new(ResourcesSuite))
10341141
}

pkg/mcp/testdata/toolsets-core-tools.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,13 +449,17 @@
449449
"readOnlyHint": true,
450450
"title": "Resources: Get"
451451
},
452-
"description": "Get a Kubernetes resource in the current cluster by providing its apiVersion, kind, optionally the namespace, and its name\n(common apiVersion and kind include: v1 Pod, v1 Service, v1 Node, apps/v1 Deployment, networking.k8s.io/v1 Ingress)",
452+
"description": "Get a Kubernetes resource in the current cluster by providing its apiVersion, kind, optionally the namespace, and its name. Use the optional gotemplate parameter to extract specific fields instead of returning full YAML (same syntax as oc get -o go-template).\n(common apiVersion and kind include: v1 Pod, v1 Service, v1 Node, apps/v1 Deployment, networking.k8s.io/v1 Ingress)",
453453
"inputSchema": {
454454
"properties": {
455455
"apiVersion": {
456456
"description": "apiVersion of the resource (examples of valid apiVersion are: v1, apps/v1, networking.k8s.io/v1)",
457457
"type": "string"
458458
},
459+
"gotemplate": {
460+
"description": "Optional Go template to extract specific fields instead of returning full YAML (e.g. {{.spec.source.repoURL}}, {{.status.phase}})",
461+
"type": "string"
462+
},
459463
"kind": {
460464
"description": "kind of the resource (examples of valid kind are: Pod, Service, Deployment, Ingress)",
461465
"type": "string"
@@ -486,7 +490,7 @@
486490
"readOnlyHint": true,
487491
"title": "Resources: List"
488492
},
489-
"description": "List Kubernetes resources and objects in the current cluster by providing their apiVersion and kind and optionally the namespace and label selector\n(common apiVersion and kind include: v1 Pod, v1 Service, v1 Node, apps/v1 Deployment, networking.k8s.io/v1 Ingress)",
493+
"description": "List Kubernetes resources and objects in the current cluster by providing their apiVersion and kind and optionally the namespace and label selector. Use the optional gotemplate parameter to extract specific fields instead of returning full YAML (same syntax as oc get -o go-template).\n(common apiVersion and kind include: v1 Pod, v1 Service, v1 Node, apps/v1 Deployment, networking.k8s.io/v1 Ingress)",
490494
"inputSchema": {
491495
"properties": {
492496
"apiVersion": {
@@ -498,6 +502,10 @@
498502
"pattern": "^[.\\-A-Za-z0-9]+([=!,]{1,2}[.\\-A-Za-z0-9]+)+$",
499503
"type": "string"
500504
},
505+
"gotemplate": {
506+
"description": "Optional Go template to extract specific fields instead of returning full YAML (e.g. {{range .items}}{{.metadata.name}}\\n{{end}}, {{.spec.source.repoURL}})",
507+
"type": "string"
508+
},
501509
"kind": {
502510
"description": "kind of the resources (examples of valid kind are: Pod, Service, Deployment, Ingress)",
503511
"type": "string"

pkg/mcp/testdata/toolsets-full-tools-multicluster.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@
546546
"readOnlyHint": true,
547547
"title": "Resources: Get"
548548
},
549-
"description": "Get a Kubernetes resource in the current cluster by providing its apiVersion, kind, optionally the namespace, and its name\n(common apiVersion and kind include: v1 Pod, v1 Service, v1 Node, apps/v1 Deployment, networking.k8s.io/v1 Ingress)",
549+
"description": "Get a Kubernetes resource in the current cluster by providing its apiVersion, kind, optionally the namespace, and its name. Use the optional gotemplate parameter to extract specific fields instead of returning full YAML (same syntax as oc get -o go-template).\n(common apiVersion and kind include: v1 Pod, v1 Service, v1 Node, apps/v1 Deployment, networking.k8s.io/v1 Ingress)",
550550
"inputSchema": {
551551
"properties": {
552552
"apiVersion": {
@@ -557,6 +557,10 @@
557557
"description": "Optional parameter selecting which context to run the tool in. Defaults to fake-context if not set",
558558
"type": "string"
559559
},
560+
"gotemplate": {
561+
"description": "Optional Go template to extract specific fields instead of returning full YAML (e.g. {{.spec.source.repoURL}}, {{.status.phase}})",
562+
"type": "string"
563+
},
560564
"kind": {
561565
"description": "kind of the resource (examples of valid kind are: Pod, Service, Deployment, Ingress)",
562566
"type": "string"
@@ -587,7 +591,7 @@
587591
"readOnlyHint": true,
588592
"title": "Resources: List"
589593
},
590-
"description": "List Kubernetes resources and objects in the current cluster by providing their apiVersion and kind and optionally the namespace and label selector\n(common apiVersion and kind include: v1 Pod, v1 Service, v1 Node, apps/v1 Deployment, networking.k8s.io/v1 Ingress)",
594+
"description": "List Kubernetes resources and objects in the current cluster by providing their apiVersion and kind and optionally the namespace and label selector. Use the optional gotemplate parameter to extract specific fields instead of returning full YAML (same syntax as oc get -o go-template).\n(common apiVersion and kind include: v1 Pod, v1 Service, v1 Node, apps/v1 Deployment, networking.k8s.io/v1 Ingress)",
591595
"inputSchema": {
592596
"properties": {
593597
"apiVersion": {
@@ -603,6 +607,10 @@
603607
"pattern": "^[.\\-A-Za-z0-9]+([=!,]{1,2}[.\\-A-Za-z0-9]+)+$",
604608
"type": "string"
605609
},
610+
"gotemplate": {
611+
"description": "Optional Go template to extract specific fields instead of returning full YAML (e.g. {{range .items}}{{.metadata.name}}\\n{{end}}, {{.spec.source.repoURL}})",
612+
"type": "string"
613+
},
606614
"kind": {
607615
"description": "kind of the resources (examples of valid kind are: Pod, Service, Deployment, Ingress)",
608616
"type": "string"

pkg/mcp/testdata/toolsets-full-tools-openshift.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -484,13 +484,17 @@
484484
"readOnlyHint": true,
485485
"title": "Resources: Get"
486486
},
487-
"description": "Get a Kubernetes resource in the current cluster by providing its apiVersion, kind, optionally the namespace, and its name\n(common apiVersion and kind include: v1 Pod, v1 Service, v1 Node, apps/v1 Deployment, networking.k8s.io/v1 Ingress, route.openshift.io/v1 Route)",
487+
"description": "Get a Kubernetes resource in the current cluster by providing its apiVersion, kind, optionally the namespace, and its name. Use the optional gotemplate parameter to extract specific fields instead of returning full YAML (same syntax as oc get -o go-template).\n(common apiVersion and kind include: v1 Pod, v1 Service, v1 Node, apps/v1 Deployment, networking.k8s.io/v1 Ingress, route.openshift.io/v1 Route)",
488488
"inputSchema": {
489489
"properties": {
490490
"apiVersion": {
491491
"description": "apiVersion of the resource (examples of valid apiVersion are: v1, apps/v1, networking.k8s.io/v1)",
492492
"type": "string"
493493
},
494+
"gotemplate": {
495+
"description": "Optional Go template to extract specific fields instead of returning full YAML (e.g. {{.spec.source.repoURL}}, {{.status.phase}})",
496+
"type": "string"
497+
},
494498
"kind": {
495499
"description": "kind of the resource (examples of valid kind are: Pod, Service, Deployment, Ingress)",
496500
"type": "string"
@@ -521,7 +525,7 @@
521525
"readOnlyHint": true,
522526
"title": "Resources: List"
523527
},
524-
"description": "List Kubernetes resources and objects in the current cluster by providing their apiVersion and kind and optionally the namespace and label selector\n(common apiVersion and kind include: v1 Pod, v1 Service, v1 Node, apps/v1 Deployment, networking.k8s.io/v1 Ingress, route.openshift.io/v1 Route)",
528+
"description": "List Kubernetes resources and objects in the current cluster by providing their apiVersion and kind and optionally the namespace and label selector. Use the optional gotemplate parameter to extract specific fields instead of returning full YAML (same syntax as oc get -o go-template).\n(common apiVersion and kind include: v1 Pod, v1 Service, v1 Node, apps/v1 Deployment, networking.k8s.io/v1 Ingress, route.openshift.io/v1 Route)",
525529
"inputSchema": {
526530
"properties": {
527531
"apiVersion": {
@@ -533,6 +537,10 @@
533537
"pattern": "^[.\\-A-Za-z0-9]+([=!,]{1,2}[.\\-A-Za-z0-9]+)+$",
534538
"type": "string"
535539
},
540+
"gotemplate": {
541+
"description": "Optional Go template to extract specific fields instead of returning full YAML (e.g. {{range .items}}{{.metadata.name}}\\n{{end}}, {{.spec.source.repoURL}})",
542+
"type": "string"
543+
},
536544
"kind": {
537545
"description": "kind of the resources (examples of valid kind are: Pod, Service, Deployment, Ingress)",
538546
"type": "string"

pkg/mcp/testdata/toolsets-full-tools.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -469,13 +469,17 @@
469469
"readOnlyHint": true,
470470
"title": "Resources: Get"
471471
},
472-
"description": "Get a Kubernetes resource in the current cluster by providing its apiVersion, kind, optionally the namespace, and its name\n(common apiVersion and kind include: v1 Pod, v1 Service, v1 Node, apps/v1 Deployment, networking.k8s.io/v1 Ingress)",
472+
"description": "Get a Kubernetes resource in the current cluster by providing its apiVersion, kind, optionally the namespace, and its name. Use the optional gotemplate parameter to extract specific fields instead of returning full YAML (same syntax as oc get -o go-template).\n(common apiVersion and kind include: v1 Pod, v1 Service, v1 Node, apps/v1 Deployment, networking.k8s.io/v1 Ingress)",
473473
"inputSchema": {
474474
"properties": {
475475
"apiVersion": {
476476
"description": "apiVersion of the resource (examples of valid apiVersion are: v1, apps/v1, networking.k8s.io/v1)",
477477
"type": "string"
478478
},
479+
"gotemplate": {
480+
"description": "Optional Go template to extract specific fields instead of returning full YAML (e.g. {{.spec.source.repoURL}}, {{.status.phase}})",
481+
"type": "string"
482+
},
479483
"kind": {
480484
"description": "kind of the resource (examples of valid kind are: Pod, Service, Deployment, Ingress)",
481485
"type": "string"
@@ -506,7 +510,7 @@
506510
"readOnlyHint": true,
507511
"title": "Resources: List"
508512
},
509-
"description": "List Kubernetes resources and objects in the current cluster by providing their apiVersion and kind and optionally the namespace and label selector\n(common apiVersion and kind include: v1 Pod, v1 Service, v1 Node, apps/v1 Deployment, networking.k8s.io/v1 Ingress)",
513+
"description": "List Kubernetes resources and objects in the current cluster by providing their apiVersion and kind and optionally the namespace and label selector. Use the optional gotemplate parameter to extract specific fields instead of returning full YAML (same syntax as oc get -o go-template).\n(common apiVersion and kind include: v1 Pod, v1 Service, v1 Node, apps/v1 Deployment, networking.k8s.io/v1 Ingress)",
510514
"inputSchema": {
511515
"properties": {
512516
"apiVersion": {
@@ -518,6 +522,10 @@
518522
"pattern": "^[.\\-A-Za-z0-9]+([=!,]{1,2}[.\\-A-Za-z0-9]+)+$",
519523
"type": "string"
520524
},
525+
"gotemplate": {
526+
"description": "Optional Go template to extract specific fields instead of returning full YAML (e.g. {{range .items}}{{.metadata.name}}\\n{{end}}, {{.spec.source.repoURL}})",
527+
"type": "string"
528+
},
521529
"kind": {
522530
"description": "kind of the resources (examples of valid kind are: Pod, Service, Deployment, Ingress)",
523531
"type": "string"

0 commit comments

Comments
 (0)