From: Dhairya Parmar Date: Wed, 13 Sep 2023 18:55:25 +0000 (+0530) Subject: mgr: make object_format's Responder class capable of responding err status X-Git-Tag: v19.0.0~19^2~3 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=3a5381326c3e5e88080f6b9e249383db67fcb622;p=ceph-ci.git mgr: make object_format's Responder class capable of responding err status Fixes: https://tracker.ceph.com/issues/62641 Signed-off-by: Dhairya Parmar --- diff --git a/src/pybind/mgr/object_format.py b/src/pybind/mgr/object_format.py index b53bc3eb060..8b60aa1b3dc 100644 --- a/src/pybind/mgr/object_format.py +++ b/src/pybind/mgr/object_format.py @@ -235,6 +235,15 @@ class ReturnValueProvider(Protocol): ... # pragma: no cover +class StatusValueProvider(Protocol): + def mgr_status_value(self) -> str: + """Return a string value to provide the Ceph MGR with an error status + for the MGR's response tuple. Empty string means success. Return a string + containing error info otherwise. + """ + ... # pragma: no cover + + class CommonFormatter(Protocol): """A protocol that indicates the type is a formatter for multiple possible formats. @@ -276,6 +285,11 @@ def _is_return_value_provider(obj: ReturnValueProvider) -> bool: return callable(getattr(obj, 'mgr_return_value', None)) +def _is_status_value_provider(obj: StatusValueProvider) -> bool: + """Return true if obj is usable as a StatusValueProvider""" + return callable(getattr(obj, 'mgr_status_value', None)) + + class ObjectFormatAdapter: """A format adapater for a single object. Given an input object, this type will adapt the object, or a simplified @@ -366,6 +380,27 @@ class ReturnValueAdapter: return self.default_return_value +class StatusValueAdapter: + """A status-value adapter for an object. + Given an input object, this type will attempt to get a mgr status value + from the object if provides a `mgr_status_value` function. + If not it returns a default status value, typically an empty string. + """ + + def __init__( + self, + obj: Any, + default: str = "", + ) -> None: + self.obj = obj + self.default_status = default + + def mgr_status_value(self) -> str: + if _is_status_value_provider(self.obj): + return str(self.obj.mgr_status_value()) + return self.default_status + + class ErrorResponseBase(Exception): """An exception that can directly be converted to a mgr reponse.""" @@ -448,6 +483,7 @@ ObjectResponseFuncType = Union[ Callable[..., JSONDataProvider], Callable[..., YAMLDataProvider], Callable[..., ReturnValueProvider], + Callable[..., StatusValueProvider], ] @@ -487,6 +523,10 @@ class Responder: """Return a ReturnValueProvider for the given object.""" return ReturnValueAdapter(obj) + def _statusval_provider(self, obj: Any) -> StatusValueProvider: + """Return a StatusValueProvider for the given object.""" + return StatusValueAdapter(obj) + def _get_format_func( self, obj: Any, format_req: Optional[str] = None ) -> Callable: @@ -515,6 +555,12 @@ class Responder: """Return a mgr return-value for the given object (usually zero).""" return self._retval_provider(obj).mgr_return_value() + def _return_status(self, obj: Any) -> str: + """Return a mgr status-value for the given object (usually empty + string). + """ + return self._statusval_provider(obj).mgr_status_value() + def __call__(self, f: ObjectResponseFuncType) -> HandlerFuncType: """Wrap a python function so that the original function's return value becomes the source for an automatically formatted mgr response. @@ -528,9 +574,10 @@ class Responder: robj = f(*args, **kwargs) body = self._formatted(robj, format_req) retval = self._return_value(robj) + statusval = self._return_status(robj) except ErrorResponseBase as e: return e.format_response() - return retval, body, "" + return retval, body, statusval # set the extra args on our wrapper function. this will be consumed by # the CLICommand decorator and added to the set of optional arguments