Skip to content
This repository was archived by the owner on Jan 23, 2026. It is now read-only.

Commit 74d142c

Browse files
authored
Merge pull request #344 from jumpstarter-dev/grpc-exception
Global exception handling for j command
2 parents 28d6b1c + 2bed0fb commit 74d142c

3 files changed

Lines changed: 45 additions & 7 deletions

File tree

packages/jumpstarter-cli-client/jumpstarter_cli_client/__init__.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import logging
2+
import sys
23
from typing import Optional
34

45
import asyncclick as click
56
from jumpstarter_cli_common import AliasedGroup, opt_log_level, version
7+
from jumpstarter_cli_common.exceptions import handle_exceptions
68

79
from .client_config import create_client_config, delete_client_config, list_client_configs, use_client_config
810
from .client_exporter import list_client_exporters
@@ -24,7 +26,16 @@ def client(log_level: Optional[str]):
2426

2527
def j():
2628
with env() as client:
27-
client.cli()(standalone_mode=True)
29+
30+
@handle_exceptions
31+
def cli():
32+
client.cli()(standalone_mode=False)
33+
34+
try:
35+
cli()
36+
except click.ClickException as e:
37+
e.show()
38+
sys.exit(1)
2839

2940

3041
client.add_command(create_client_config)

packages/jumpstarter/jumpstarter/client/core.py

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from jumpstarter_protocol import jumpstarter_pb2, jumpstarter_pb2_grpc, router_pb2_grpc
1414

1515
from jumpstarter.common import Metadata
16+
from jumpstarter.common.exceptions import JumpstarterException
1617
from jumpstarter.common.resources import ResourceMetadata
1718
from jumpstarter.common.serde import decode_value, encode_value
1819
from jumpstarter.common.streams import (
@@ -29,6 +30,24 @@
2930
)
3031

3132

33+
class DriverError(JumpstarterException):
34+
"""
35+
Raised when a driver call returns an error
36+
"""
37+
38+
39+
class DriverMethodNotImplemented(DriverError, NotImplementedError):
40+
"""
41+
Raised when a driver method is not implemented
42+
"""
43+
44+
45+
class DriverInvalidArgument(DriverError, ValueError):
46+
"""
47+
Raised when a driver method is called with invalid arguments
48+
"""
49+
50+
3251
@dataclass(kw_only=True)
3352
class AsyncDriverClient(
3453
Metadata,
@@ -74,11 +93,13 @@ async def call_async(self, method, *args):
7493
except AioRpcError as e:
7594
match e.code():
7695
case StatusCode.UNIMPLEMENTED:
77-
raise NotImplementedError(e.details()) from None
96+
raise DriverMethodNotImplemented(e.details()) from None
7897
case StatusCode.INVALID_ARGUMENT:
79-
raise ValueError(e.details()) from None
98+
raise DriverInvalidArgument(e.details()) from None
99+
case StatusCode.UNKNOWN:
100+
raise DriverError(e.details()) from None
80101
case _:
81-
raise
102+
raise DriverError(e.details()) from e
82103

83104
return decode_value(response.result)
84105

@@ -97,11 +118,13 @@ async def streamingcall_async(self, method, *args):
97118
except AioRpcError as e:
98119
match e.code():
99120
case StatusCode.UNIMPLEMENTED:
100-
raise NotImplementedError(e.details()) from None
121+
raise DriverMethodNotImplemented(e.details()) from None
101122
case StatusCode.INVALID_ARGUMENT:
102-
raise ValueError(e.details()) from None
123+
raise DriverInvalidArgument(e.details()) from None
124+
case StatusCode.UNKNOWN:
125+
raise DriverError(e.details()) from None
103126
case _:
104-
raise
127+
raise DriverError(e.details()) from e
105128

106129
@asynccontextmanager
107130
async def stream_async(self, method):

packages/jumpstarter/jumpstarter/driver/base.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ async def DriverCall(self, request, context):
108108
await context.abort(StatusCode.INVALID_ARGUMENT, str(e))
109109
except TimeoutError as e:
110110
await context.abort(StatusCode.DEADLINE_EXCEEDED, str(e))
111+
except Exception as e:
112+
await context.abort(StatusCode.UNKNOWN, str(e))
111113

112114
async def StreamingDriverCall(self, request, context):
113115
"""
@@ -136,6 +138,8 @@ async def StreamingDriverCall(self, request, context):
136138
await context.abort(StatusCode.INVALID_ARGUMENT, str(e))
137139
except TimeoutError as e:
138140
await context.abort(StatusCode.DEADLINE_EXCEEDED, str(e))
141+
except Exception as e:
142+
await context.abort(StatusCode.UNKNOWN, str(e))
139143

140144
@asynccontextmanager
141145
async def Stream(self, request, context):

0 commit comments

Comments
 (0)