diff --git a/README.md b/README.md index a70303f..be5c11a 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,13 @@ Some codes raise a subclass of `DockError`, so you can catch them directly: `ConnectorNotConnectedError` (`connector_not_connected`, 409), `ConnectorAdminOnlyError` (`connector_admin_only`, 403), `ConnectorNotFoundError` (`connector_not_found`, 404), `ImageUnknownError` -(`image_unknown`, 400) and `ImageUnavailableError` (`image_unavailable`, 400). +(`image_unknown`, 400), `ImageUnavailableError` (`image_unavailable`, 400), +`PortNotFoundError` (`port_not_found`, 404), `PortLimitReachedError` +(`port_limit_reached`, 409) and `PortsUnavailableError` (`ports_unavailable`, +503). + +Port 2222 is reserved for the dock agent and is rejected with +`validation_error`. A dock can expose at most 10 ports. ## Configuration diff --git a/src/usedock/__init__.py b/src/usedock/__init__.py index 80ed42f..c2b59aa 100644 --- a/src/usedock/__init__.py +++ b/src/usedock/__init__.py @@ -6,6 +6,9 @@ DockError, ImageUnavailableError, ImageUnknownError, + PortLimitReachedError, + PortNotFoundError, + PortsUnavailableError, ) from .models import ( Connector, @@ -36,4 +39,7 @@ "ImageUnknownError", "Operation", "Port", + "PortLimitReachedError", + "PortNotFoundError", + "PortsUnavailableError", ] diff --git a/src/usedock/errors.py b/src/usedock/errors.py index f6450f1..39d1126 100644 --- a/src/usedock/errors.py +++ b/src/usedock/errors.py @@ -39,12 +39,27 @@ class ImageUnavailableError(DockError): """``image_unavailable`` (400): the image is in the catalog but no host serves it right now.""" +class PortNotFoundError(DockError): + """``port_not_found`` (404): closing a port that is not exposed.""" + + +class PortLimitReachedError(DockError): + """``port_limit_reached`` (409): a dock already exposes the maximum of 10 ports.""" + + +class PortsUnavailableError(DockError): + """``ports_unavailable`` (503): hosted ports are not configured on this deployment.""" + + _BY_CODE: Dict[str, Type[DockError]] = { "connector_not_connected": ConnectorNotConnectedError, "connector_admin_only": ConnectorAdminOnlyError, "connector_not_found": ConnectorNotFoundError, "image_unknown": ImageUnknownError, "image_unavailable": ImageUnavailableError, + "port_not_found": PortNotFoundError, + "port_limit_reached": PortLimitReachedError, + "ports_unavailable": PortsUnavailableError, } diff --git a/tests/test_client.py b/tests/test_client.py index 545ec16..abc8964 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -23,6 +23,9 @@ DockState, ImageUnavailableError, ImageUnknownError, + PortLimitReachedError, + PortNotFoundError, + PortsUnavailableError, ) from usedock.client import MAX_COMMAND_BYTES, shell_quote @@ -642,6 +645,9 @@ def test_images_list() -> None: ("connector_admin_only", 403, ConnectorAdminOnlyError), ("image_unknown", 400, ImageUnknownError), ("image_unavailable", 400, ImageUnavailableError), + ("port_not_found", 404, PortNotFoundError), + ("port_limit_reached", 409, PortLimitReachedError), + ("ports_unavailable", 503, PortsUnavailableError), ], ) def test_new_error_codes_raise_typed_errors(code: str, status: int, cls: type) -> None: