diff --git a/UPDATING.md b/UPDATING.md index 8f5785ac8c97d..4dd68340bcdb4 100644 --- a/UPDATING.md +++ b/UPDATING.md @@ -30,6 +30,7 @@ assists people when migrating to a new version. ### Breaking Changes +- [27130](https://github.com/apache/superset/pull/27130): Fixes the DELETE `/database/{id}/ssh_tunnel/`` endpoint to now correctly accept a database ID as a parameter, rather than an SSH tunnel ID. - [27117](https://github.com/apache/superset/pull/27117): Removes the following deprecated endpoints: `/superset/sqllab`, `/superset/sqllab/history`, `/sqllab/my_queries` use `/sqllab`, `/sqllab/history`, `/savedqueryview/list/?_flt_0_user={get_user_id()}` instead. - [26347](https://github.com/apache/superset/issues/26347): Removes the deprecated `VERSIONED_EXPORT` feature flag. The previous value of the feature flag was `True` and now the feature is permanently enabled. - [26328](https://github.com/apache/superset/issues/26328): Removes the deprecated Filter Box code and it's associated dependencies `react-select` and `array-move`. It also removes the `DeprecatedSelect` and `AsyncSelect` components that were exclusively used by filter boxes. Existing filter boxes will be automatically migrated to native filters. diff --git a/superset/databases/api.py b/superset/databases/api.py index 62fb72943749f..2f95bd0442754 100644 --- a/superset/databases/api.py +++ b/superset/databases/api.py @@ -22,6 +22,7 @@ from typing import Any, cast, Optional from zipfile import is_zipfile, ZipFile +from deprecation import deprecated from flask import request, Response, send_file from flask_appbuilder.api import expose, protect, rison, safe from flask_appbuilder.models.sqla.interface import SQLAInterface @@ -48,7 +49,6 @@ from superset.commands.database.ssh_tunnel.exceptions import ( SSHTunnelDeleteFailedError, SSHTunnelingNotEnabledError, - SSHTunnelNotFoundError, ) from superset.commands.database.tables import TablesDatabaseCommand from superset.commands.database.test_connection import TestConnectionDatabaseCommand @@ -1447,6 +1447,7 @@ def validate_parameters(self) -> FlaskResponse: @expose("//ssh_tunnel/", methods=("DELETE",)) @protect() @statsd_metrics + @deprecated(deprecated_in="4.0") @event_logger.log_this_with_context( action=lambda self, *args, **kwargs: f"{self.__class__.__name__}" f".delete_ssh_tunnel", @@ -1483,10 +1484,15 @@ def delete_ssh_tunnel(self, pk: int) -> Response: 500: $ref: '#/components/responses/500' """ + + database = DatabaseDAO.find_by_id(pk) + if not database: + return self.response_404() try: - DeleteSSHTunnelCommand(pk).run() - return self.response(200, message="OK") - except SSHTunnelNotFoundError: + existing_ssh_tunnel_model = database.ssh_tunnels + if existing_ssh_tunnel_model: + DeleteSSHTunnelCommand(existing_ssh_tunnel_model.id).run() + return self.response(200, message="OK") return self.response_404() except SSHTunnelDeleteFailedError as ex: logger.error( diff --git a/tests/unit_tests/databases/api_test.py b/tests/unit_tests/databases/api_test.py index f867f82a98d8c..c0e1723fd8361 100644 --- a/tests/unit_tests/databases/api_test.py +++ b/tests/unit_tests/databases/api_test.py @@ -458,7 +458,9 @@ def test_delete_ssh_tunnel( assert 1 == response_tunnel.database_id # Delete the recently created SSHTunnel - response_delete_tunnel = client.delete("/api/v1/database/1/ssh_tunnel/") + response_delete_tunnel = client.delete( + f"/api/v1/database/{database.id}/ssh_tunnel/" + ) assert response_delete_tunnel.json["message"] == "OK" response_tunnel = DatabaseDAO.get_ssh_tunnel(1)