Skip to content

Commit 1110926

Browse files
authored
fix: server schema (#16)
* fix: server schema * fix: apply suggestion
1 parent 93454fa commit 1110926

File tree

5 files changed

+64
-38
lines changed

5 files changed

+64
-38
lines changed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ packages = ["src/openstack_mcp_server"]
2929

3030
[tool.pytest.ini_options]
3131
testpaths = ["tests"]
32+
pythonpath = ["src"]
3233

3334
python_files = ["test_*.py", "*_test.py"]
3435
python_classes = ["Test*"]

src/openstack_mcp_server/tools/nova_tools.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from .base import get_openstack_conn
22
from fastmcp import FastMCP
3+
from openstack_mcp_server.tools.response.nova import Server
34

45

56
class NovaTools:
@@ -13,21 +14,36 @@ def register_tools(self, mcp: FastMCP):
1314
"""
1415

1516
mcp.tool()(self.get_nova_servers)
17+
mcp.tool()(self.get_nova_server)
1618

17-
def get_nova_servers(self) -> str:
19+
def get_nova_servers(self) -> list[Server]:
1820
"""
1921
Get the list of Nova servers by invoking the registered tool.
2022
21-
:return: A string containing the names, IDs, and statuses of the servers.
23+
:return: A list of Server objects representing the Nova servers.
2224
"""
2325
# Initialize connection
2426
conn = get_openstack_conn()
2527

2628
# List the servers
2729
server_list = []
28-
for server in conn.compute.list_servers():
30+
for server in conn.compute.servers():
2931
server_list.append(
30-
f"{server.name} ({server.id}) - Status: {server.status}"
32+
Server(name=server.name, id=server.id, status=server.status)
3133
)
3234

33-
return "\n".join(server_list)
35+
return server_list
36+
37+
def get_nova_server(self, id: str) -> Server:
38+
"""
39+
Get a specific Nova server by invoking the registered tool.
40+
41+
:param id: The ID of the server to retrieve.
42+
:return: A Server object representing the Nova server.
43+
"""
44+
# Initialize connection
45+
conn = get_openstack_conn()
46+
47+
# Get a specific server (for example, the first one)
48+
server = conn.compute.get_server(id)
49+
return Server(name=server.name, id=server.id, status=server.status)

src/openstack_mcp_server/tools/response/__init__.py

Whitespace-only changes.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from pydantic import BaseModel
2+
3+
4+
class Server(BaseModel):
5+
"""A model to represent a Nova server."""
6+
7+
name: str
8+
id: str
9+
status: str

tests/tools/test_nova_tools.py

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import pytest
2-
from unittest.mock import Mock
1+
from unittest.mock import Mock, call
2+
from openstack_mcp_server.tools.response.nova import Server
33
from openstack_mcp_server.tools.nova_tools import NovaTools
44

55

@@ -21,37 +21,37 @@ def test_get_nova_servers_success(self, mock_get_openstack_conn):
2121
mock_server2.id = "xyz789-uvw456-rst123"
2222
mock_server2.status = "SHUTOFF"
2323

24-
# Configure mock compute.list_servers()
25-
mock_conn.compute.list_servers.return_value = [mock_server1, mock_server2]
24+
# Configure mock compute.servers()
25+
mock_conn.compute.servers.return_value = [mock_server1, mock_server2]
2626

2727
# Test NovaTools
2828
nova_tools = NovaTools()
2929
result = nova_tools.get_nova_servers()
3030

3131
# Verify results
32-
expected_output = (
33-
"web-server-01 (abc123-def456-ghi789) - Status: ACTIVE\n"
34-
"db-server-01 (xyz789-uvw456-rst123) - Status: SHUTOFF"
35-
)
32+
expected_output = [
33+
Server(name="web-server-01", id="abc123-def456-ghi789", status="ACTIVE"),
34+
Server(name="db-server-01", id="xyz789-uvw456-rst123", status="SHUTOFF"),
35+
]
3636
assert result == expected_output
3737

3838
# Verify mock calls
39-
mock_conn.compute.list_servers.assert_called_once()
39+
mock_conn.compute.servers.assert_called_once()
4040

4141
def test_get_nova_servers_empty_list(self, mock_get_openstack_conn):
4242
"""Test getting nova servers when no servers exist."""
4343
mock_conn = mock_get_openstack_conn
4444

4545
# Empty server list
46-
mock_conn.compute.list_servers.return_value = []
46+
mock_conn.compute.servers.return_value = []
4747

4848
nova_tools = NovaTools()
4949
result = nova_tools.get_nova_servers()
5050

51-
# Verify empty string
52-
assert result == ""
51+
# Verify empty list
52+
assert result == []
5353

54-
mock_conn.compute.list_servers.assert_called_once()
54+
mock_conn.compute.servers.assert_called_once()
5555

5656
def test_get_nova_servers_single_server(self, mock_get_openstack_conn):
5757
"""Test getting nova servers with a single server."""
@@ -63,15 +63,15 @@ def test_get_nova_servers_single_server(self, mock_get_openstack_conn):
6363
mock_server.id = "single-123"
6464
mock_server.status = "BUILDING"
6565

66-
mock_conn.compute.list_servers.return_value = [mock_server]
66+
mock_conn.compute.servers.return_value = [mock_server]
6767

6868
nova_tools = NovaTools()
6969
result = nova_tools.get_nova_servers()
7070

71-
expected_output = "test-server (single-123) - Status: BUILDING"
71+
expected_output = [Server(name="test-server", id="single-123", status="BUILDING")]
7272
assert result == expected_output
7373

74-
mock_conn.compute.list_servers.assert_called_once()
74+
mock_conn.compute.servers.assert_called_once()
7575

7676
def test_get_nova_servers_multiple_statuses(self, mock_get_openstack_conn):
7777
"""Test servers with various statuses."""
@@ -94,20 +94,19 @@ def test_get_nova_servers_multiple_statuses(self, mock_get_openstack_conn):
9494
mock_server.status = status
9595
mock_servers.append(mock_server)
9696

97-
mock_conn.compute.list_servers.return_value = mock_servers
97+
mock_conn.compute.servers.return_value = mock_servers
9898

9999
nova_tools = NovaTools()
100100
result = nova_tools.get_nova_servers()
101101

102102
# Verify each server is included in the result
103103
for name, server_id, status in servers_data:
104-
expected_line = f"{name} ({server_id}) - Status: {status}"
105-
assert expected_line in result
106-
107-
# Verify line count (5 servers)
108-
assert len(result.split('\n')) == 5
104+
assert any(
105+
server.name == name and server.id == server_id and server.status == status
106+
for server in result
107+
)
109108

110-
mock_conn.compute.list_servers.assert_called_once()
109+
mock_conn.compute.servers.assert_called_once()
111110

112111
def test_get_nova_servers_with_special_characters(self, mock_get_openstack_conn):
113112
"""Test servers with special characters in names."""
@@ -124,15 +123,16 @@ def test_get_nova_servers_with_special_characters(self, mock_get_openstack_conn)
124123
mock_server2.id = "id.with.dots"
125124
mock_server2.status = "SHUTOFF"
126125

127-
mock_conn.compute.list_servers.return_value = [mock_server1, mock_server2]
126+
mock_conn.compute.servers.return_value = [mock_server1, mock_server2]
128127

129128
nova_tools = NovaTools()
130129
result = nova_tools.get_nova_servers()
131130

132-
assert "web-server_test-01 (id-with-dashes) - Status: ACTIVE" in result
133-
assert "db.server.prod (id.with.dots) - Status: SHUTOFF" in result
131+
assert Server(name="web-server_test-01", id="id-with-dashes", status="ACTIVE") in result
132+
assert Server(name="db.server.prod", id="id.with.dots", status="SHUTOFF") in result
133+
134134

135-
mock_conn.compute.list_servers.assert_called_once()
135+
mock_conn.compute.servers.assert_called_once()
136136

137137
def test_register_tools(self):
138138
"""Test that tools are properly registered with FastMCP."""
@@ -143,12 +143,12 @@ def test_register_tools(self):
143143

144144
nova_tools = NovaTools()
145145
nova_tools.register_tools(mock_mcp)
146-
147-
# Verify mcp.tool() was called
148-
mock_mcp.tool.assert_called_once()
149-
150-
# Verify decorator was applied to get_nova_servers method
151-
mock_tool_decorator.assert_called_once_with(nova_tools.get_nova_servers)
146+
147+
mock_tool_decorator.assert_has_calls([
148+
call(nova_tools.get_nova_servers),
149+
call(nova_tools.get_nova_server)
150+
])
151+
assert mock_tool_decorator.call_count == 2
152152

153153
def test_nova_tools_instantiation(self):
154154
"""Test NovaTools can be instantiated."""

0 commit comments

Comments
 (0)