Skip to content

Commit 919942c

Browse files
xingyugXingyu Guo
andauthored
fix(models): accept null values in FilesystemInfo for container mount… (#330)
fix(models): accept null values in FilesystemInfo for container mount filesystems On Kubernetes worker nodes, findmnt --df --json returns null for size, used, avail, and use% fields on projected volumes, CSI volumes, and subpath mounts. The FilesystemInfo model rejected these with ValidationError because fields were typed as str instead of str | None. Co-authored-by: Xingyu Guo <xingyu.guo@ericsson.com>
1 parent 3024bc6 commit 919942c

2 files changed

Lines changed: 49 additions & 7 deletions

File tree

src/linux_mcp_server/models.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,13 +133,13 @@ class CpuInfo(BaseModel):
133133
class FilesystemInfo(BaseModel):
134134
"""Individual filesystem entry from findmnt output."""
135135

136-
source: str = ""
137-
fstype: str = ""
138-
size: str = ""
139-
used: str = ""
140-
avail: str = ""
141-
use_percent: str = Field(default="", alias="use%")
142-
target: str = ""
136+
source: str | None = ""
137+
fstype: str | None = ""
138+
size: str | None = ""
139+
used: str | None = ""
140+
avail: str | None = ""
141+
use_percent: str | None = Field(default="", alias="use%")
142+
target: str | None = ""
143143

144144
model_config = {"populate_by_name": True}
145145

tests/tools/test_system_info.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Tests for system information tools."""
22

3+
import json
34
import sys
45

56
import pytest
@@ -157,6 +158,47 @@ async def test_get_disk_usage_invalid_json(mcp_client, mock_execute):
157158
await mcp_client.call_tool("get_disk_usage")
158159

159160

161+
async def test_get_disk_usage_null_filesystem_fields(mcp_client, mock_execute):
162+
"""Test get_disk_usage handles null size/used/avail/use% from container mounts.
163+
164+
On Kubernetes worker nodes, findmnt returns null for projected volumes,
165+
CSI volumes, and subpath mounts.
166+
"""
167+
findmnt_json = json.dumps(
168+
{
169+
"filesystems": [
170+
{
171+
"source": "/dev/sda1",
172+
"fstype": "ext4",
173+
"size": "100G",
174+
"used": "50G",
175+
"avail": "50G",
176+
"use%": "50%",
177+
"target": "/",
178+
},
179+
{
180+
"source": "tmpfs",
181+
"fstype": "tmpfs",
182+
"size": None,
183+
"used": None,
184+
"avail": None,
185+
"use%": None,
186+
"target": "/var/lib/kubelet/pods/abc/volumes/kubernetes.io~projected/kube-api-access",
187+
},
188+
]
189+
}
190+
)
191+
mock_execute.return_value = (0, findmnt_json, "")
192+
193+
result = await mcp_client.call_tool("get_disk_usage")
194+
result_text = result.content[0].text
195+
parsed = json.loads(result_text)
196+
197+
assert len(parsed["filesystems"]) == 2
198+
assert parsed["filesystems"][0]["size"] == "100G"
199+
assert parsed["filesystems"][1]["size"] is None
200+
201+
160202
async def test_get_hardware_information_unexpected_exception(mcp_client, mock_execute):
161203
"""Test get_hardware_information with unexpected exception from command execution."""
162204
# Mock cmd.run to raise an unexpected exception (not FileNotFoundError)

0 commit comments

Comments
 (0)