Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(BA-517): Raise exception if multiple VFolders exist in decorator #3465

Merged
merged 1 commit into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/3465.fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Raise exception if multiple VFolders exist in decorator
15 changes: 7 additions & 8 deletions src/ai/backend/manager/api/vfolder.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,14 +191,13 @@ async def _wrapped(
*args: P.args,
**kwargs: P.kwargs,
) -> web.Response:
for row in folder_rows:
try:
await check_vfolder_status(row, status)
return await handler(request, row, *args, **kwargs)
except VFolderFilterStatusFailed:
pass
# none of our candidates matched the status filter, so we should instead raise error here
raise VFolderFilterStatusFailed
if len(folder_rows) > 1:
raise TooManyVFoldersFound(folder_rows)
if len(folder_rows) == 0:
raise VFolderNotFound()
row = folder_rows[0]
await check_vfolder_status(row, status)
return await handler(request, row, *args, **kwargs)

return _wrapped

Expand Down
64 changes: 61 additions & 3 deletions tests/manager/api/test_vfolder.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
from unittest.mock import AsyncMock, MagicMock
from unittest.mock import AsyncMock, MagicMock, Mock
from uuid import UUID

import pytest
from aiohttp import web

from ai.backend.manager.api import vfolder
from ai.backend.manager.api.vfolder import with_vfolder_rows_resolved
from ai.backend.manager.models.vfolder import VFolderPermissionSetAlias
from ai.backend.manager.api.exceptions import TooManyVFoldersFound, VFolderNotFound
from ai.backend.manager.api.vfolder import with_vfolder_rows_resolved, with_vfolder_status_checked
from ai.backend.manager.models.vfolder import (
VFolderPermissionSetAlias,
VFolderRow,
VFolderStatusSet,
)


@pytest.mark.asyncio
Expand All @@ -27,3 +33,55 @@ async def dummy_handler(request, row):
await dummy_handler(mock_request)
call = mock_resolver.await_args_list[1]
assert isinstance(call.args[2], str)


@pytest.mark.parametrize(
"vfolder_status",
[
VFolderStatusSet.ALL,
VFolderStatusSet.READABLE,
VFolderStatusSet.MOUNTABLE,
VFolderStatusSet.UPDATABLE,
VFolderStatusSet.DELETABLE,
VFolderStatusSet.PURGABLE,
VFolderStatusSet.RECOVERABLE,
VFolderStatusSet.INACCESSIBLE,
],
)
async def test_too_many_vfolders(vfolder_status):
@with_vfolder_status_checked(vfolder_status)
async def too_many_vfolders_handler(request, row: VFolderRow):
return AsyncMock(return_value=web.Response(text="no response"))

mock_entry = {
"id": "fake-vfolder-id",
"host": "fake-vfolder-host",
"user_email": "[email protected]",
"user": "fake-user",
"group_name": "fake-group",
"group": "fake-group-id",
}
with pytest.raises(TooManyVFoldersFound):
await too_many_vfolders_handler(Mock(), [mock_entry, mock_entry])


@pytest.mark.parametrize(
"vfolder_status",
[
VFolderStatusSet.ALL,
VFolderStatusSet.READABLE,
VFolderStatusSet.MOUNTABLE,
VFolderStatusSet.UPDATABLE,
VFolderStatusSet.DELETABLE,
VFolderStatusSet.PURGABLE,
VFolderStatusSet.RECOVERABLE,
VFolderStatusSet.INACCESSIBLE,
],
)
async def test_no_vfolders(vfolder_status):
@with_vfolder_status_checked(vfolder_status)
async def no_vfolders_handler(request, row: VFolderRow):
return AsyncMock(return_value=web.Response(text="no response"))

with pytest.raises(VFolderNotFound):
await no_vfolders_handler(Mock(), [])
Loading