Skip to content
This repository was archived by the owner on Sep 22, 2023. It is now read-only.

Commit 74cd26c

Browse files
authored
feat: Add queryfilter support (#171)
* feat: Add `filter` and `order` args to functional API and CLI, while keeping backward compatibility with older API versions. * feat: Add explicit `BackendAPIVersionError` to indicate mismatch functionality of different API versions (e.g., when `filter` is given for legacy API sessions). * fix: Handle standard-compliant GQL erros like before
1 parent 4899ed3 commit 74cd26c

File tree

17 files changed

+114
-26
lines changed

17 files changed

+114
-26
lines changed

changes/171.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add support for queryfilter (`--filter`) and ordering (`--order`) arguments for paginated lists (e.g., `ps`, `admin agents`, `admin users` commands)

src/ai/backend/client/cli/admin/agents.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,11 @@ def agent(agent_id):
118118
help='Filter agents by the given status.')
119119
@click.option('--scaling-group', '--sgroup', type=str, default=None,
120120
help='Filter agents by the scaling group.')
121-
def agents(status, scaling_group):
121+
@click.option('--filter', 'filter_', default=None,
122+
help='Set the query filter expression.')
123+
@click.option('--order', default=None,
124+
help='Set the query ordering expression.')
125+
def agents(status, scaling_group, filter_, order):
122126
'''
123127
List and manage agents.
124128
(super-admin privilege required)
@@ -151,6 +155,8 @@ def format_item(item):
151155
scaling_group,
152156
fields=[f[1] for f in fields],
153157
page_size=page_size,
158+
filter=filter_,
159+
order=order,
154160
)
155161
echo_via_pager(
156162
tabulate_items(items, fields,

src/ai/backend/client/cli/admin/keypairs.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,11 @@ def keypair():
5656
help='Show keypairs of this given user. [default: show all]')
5757
@click.option('--is-active', type=bool, default=None,
5858
help='Filter keypairs by activation.')
59-
def keypairs(ctx, user_id, is_active):
59+
@click.option('--filter', 'filter_', default=None,
60+
help='Set the query filter expression.')
61+
@click.option('--order', default=None,
62+
help='Set the query ordering expression.')
63+
def keypairs(ctx, user_id, is_active, filter_, order):
6064
'''
6165
List and manage keypairs.
6266
To show all keypairs or other user's, your access key must have the admin
@@ -96,6 +100,8 @@ def format_item(item):
96100
is_active,
97101
fields=[f[1] for f in fields],
98102
page_size=page_size,
103+
filter=filter_,
104+
order=order,
99105
)
100106
echo_via_pager(
101107
tabulate_items(items, fields, item_formatter=format_item)

src/ai/backend/client/cli/admin/sessions.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,12 @@ def transform_fields(item: SessionItem, *, in_row: bool = True) -> SessionItem:
8585
@click.option('--running', is_flag=True,
8686
help='Filter only scheduled and running sessions. Ignores --status option.')
8787
@click.option('--detail', is_flag=True, help='Show more details using more columns.')
88-
@click.option('-f', '--format', default=None, help='Display only specified fields.')
88+
@click.option('-f', '--format', default=None, help='Display only specified fields.')
89+
@click.option('--filter', 'filter_', default=None, help='Set the query filter expression.')
90+
@click.option('--order', default=None, help='Set the query ordering expression.')
8991
@click.option('--plain', is_flag=True,
9092
help='Display the session list without decorative line drawings and the header.')
91-
def sessions(status, access_key, name_only, dead, running, detail, plain, format):
93+
def sessions(status, access_key, name_only, dead, running, detail, filter_, order, plain, format):
9294
'''
9395
List and manage compute sessions.
9496
'''
@@ -169,6 +171,8 @@ def sessions(status, access_key, name_only, dead, running, detail, plain, format
169171
status, access_key,
170172
fields=[f[1] for f in fields],
171173
page_size=page_size,
174+
filter=filter_,
175+
order=order,
172176
)
173177
if name_only:
174178
echo_via_pager(

src/ai/backend/client/cli/admin/storage.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,11 @@ def storage(vfolder_host):
5151

5252

5353
@admin.command()
54-
def storage_list():
54+
@click.option('--filter', 'filter_', default=None,
55+
help='Set the query filter expression.')
56+
@click.option('--order', default=None,
57+
help='Set the query ordering expression.')
58+
def storage_list(filter_, order):
5559
"""
5660
List storage volumes.
5761
(super-admin privilege required)
@@ -68,6 +72,8 @@ def storage_list():
6872
items = session.Storage.paginated_list(
6973
fields=[f[1] for f in fields],
7074
page_size=page_size,
75+
filter=filter_,
76+
order=order,
7177
)
7278
echo_via_pager(
7379
tabulate_items(items, fields)

src/ai/backend/client/cli/admin/users.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,11 @@ def user(email):
6161
help='Filter users in a specific state (active, inactive, deleted, before-verification).')
6262
@click.option('-g', '--group', type=str, default=None,
6363
help='Filter by group ID.')
64-
def users(ctx, status, group) -> None:
64+
@click.option('--filter', 'filter_', default=None,
65+
help='Set the query filter expression.')
66+
@click.option('--order', default=None,
67+
help='Set the query ordering expression.')
68+
def users(ctx, status, group, filter_, order) -> None:
6569
'''
6670
List and manage users.
6771
(admin privilege required)
@@ -94,6 +98,8 @@ def format_item(item):
9498
status, group,
9599
fields=[f[1] for f in fields],
96100
page_size=page_size,
101+
filter=filter_,
102+
order=order,
97103
)
98104
echo_via_pager(
99105
tabulate_items(items, fields,

src/ai/backend/client/cli/admin/vfolders.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@
2222
'(only works if you are a super-admin)')
2323
@click.option('-g', '--group', type=str, default=None,
2424
help='Filter by group ID.')
25-
def vfolders(ctx, access_key, group):
25+
@click.option('--filter', 'filter_', default=None,
26+
help='Set the query filter expression.')
27+
@click.option('--order', default=None,
28+
help='Set the query ordering expression.')
29+
def vfolders(ctx, access_key, group, filter_, order):
2630
'''
2731
List and manage virtual folders.
2832
'''
@@ -50,6 +54,8 @@ def vfolders(ctx, access_key, group):
5054
group, access_key,
5155
fields=[f[1] for f in fields],
5256
page_size=page_size,
57+
filter=filter_,
58+
order=order,
5359
)
5460
echo_via_pager(
5561
tabulate_items(items, fields)

src/ai/backend/client/cli/ps.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@
2121
help='Filter only scheduled and running sessions. Ignores --status option.')
2222
@click.option('--detail', is_flag=True, help='Show more details using more columns.')
2323
@click.option('-f', '--format', default=None, help='Display only specified fields.')
24+
@click.option('--filter', 'filter_', default=None, help='Set the query filter expression.')
25+
@click.option('--order', default=None, help='Set the query ordering expression.')
2426
@click.option('--plain', is_flag=True,
2527
help='Display the session list without decorative line drawings and the header.')
2628
@click.pass_context
27-
def ps(ctx, status, name_only, dead, running, detail, plain, format):
29+
def ps(ctx, status, name_only, dead, running, detail, filter_, order, plain, format):
2830
'''
2931
Lists the current running compute sessions for the current keypair.
3032
This is an alias of the "admin sessions --status=RUNNING" command.

src/ai/backend/client/exceptions.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@ def data(self) -> Any:
4444
return self.args[2]
4545

4646

47+
class BackendAPIVersionError(BackendError):
48+
"""
49+
Exception indicating that the given operation/argument is not supported
50+
in the currently negotiated server API version.
51+
"""
52+
53+
4754
class BackendClientError(BackendError):
4855
"""
4956
Exceptions from the client library, such as argument validation

src/ai/backend/client/func/admin.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,11 @@ async def _query(
6161
response = await resp.json()
6262
errors = response.get("errors", [])
6363
if errors:
64-
raise BackendAPIError(400, reason="GraphQL-generated error", data=errors)
64+
raise BackendAPIError(400, reason="Bad request", data={
65+
'type': 'https://api.backend.ai/probs/graphql-error',
66+
'title': 'GraphQL-generated error',
67+
'data': errors,
68+
})
6569
else:
6670
return response["data"]
6771
else:

0 commit comments

Comments
 (0)