mirror of
https://github.com/apache/superset.git
synced 2026-04-19 08:04:53 +00:00
feat: add extract_errors to Postgres (#13997)
* feat: add extract_errors to Postgres * Add unit tests * Fix lint * Fix unit tests
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
# isort:skip_file
|
||||
# pylint: disable=invalid-name, no-self-use, too-many-public-methods, too-many-arguments
|
||||
"""Unit tests for Superset"""
|
||||
import dataclasses
|
||||
import json
|
||||
from io import BytesIO
|
||||
from unittest import mock
|
||||
@@ -27,10 +28,12 @@ import pytest
|
||||
import yaml
|
||||
|
||||
from sqlalchemy.engine.url import make_url
|
||||
from sqlalchemy.exc import DBAPIError
|
||||
from sqlalchemy.sql import func
|
||||
|
||||
from superset import db, security_manager
|
||||
from superset.connectors.sqla.models import SqlaTable
|
||||
from superset.errors import SupersetError
|
||||
from superset.models.core import Database
|
||||
from superset.models.reports import ReportSchedule, ReportScheduleType
|
||||
from superset.utils.core import get_example_database, get_main_database
|
||||
@@ -895,16 +898,44 @@ class TestDatabaseApi(SupersetTestCase):
|
||||
|
||||
app.config["PREVENT_UNSAFE_DB_CONNECTIONS"] = False
|
||||
|
||||
@mock.patch("superset.databases.commands.test_connection.is_hostname_valid",)
|
||||
def test_test_connection_failed_invalid_hostname(self, mock_is_hostname_valid):
|
||||
@mock.patch(
|
||||
"superset.databases.commands.test_connection.DatabaseDAO.build_db_for_connection_test",
|
||||
)
|
||||
@mock.patch("superset.databases.commands.test_connection.event_logger",)
|
||||
def test_test_connection_failed_invalid_hostname(
|
||||
self, mock_event_logger, mock_build_db
|
||||
):
|
||||
"""
|
||||
Database API: Test test connection failed due to invalid hostname
|
||||
"""
|
||||
mock_is_hostname_valid.return_value = False
|
||||
msg = 'psql: error: could not translate host name "locahost" to address: nodename nor servname provided, or not known'
|
||||
mock_build_db.return_value.set_sqlalchemy_uri.side_effect = DBAPIError(
|
||||
msg, None, None
|
||||
)
|
||||
mock_build_db.return_value.db_engine_spec.__name__ = "Some name"
|
||||
superset_error = SupersetError(
|
||||
message='Unable to resolve hostname "locahost".',
|
||||
error_type="TEST_CONNECTION_INVALID_HOSTNAME_ERROR",
|
||||
level="error",
|
||||
extra={
|
||||
"hostname": "locahost",
|
||||
"issue_codes": [
|
||||
{
|
||||
"code": 1007,
|
||||
"message": (
|
||||
"Issue 1007 - The hostname provided can't be resolved."
|
||||
),
|
||||
}
|
||||
],
|
||||
},
|
||||
)
|
||||
mock_build_db.return_value.db_engine_spec.extract_errors.return_value = [
|
||||
superset_error
|
||||
]
|
||||
|
||||
self.login("admin")
|
||||
data = {
|
||||
"sqlalchemy_uri": "postgres://username:password@invalidhostname:12345/db",
|
||||
"sqlalchemy_uri": "postgres://username:password@locahost:12345/db",
|
||||
"database_name": "examples",
|
||||
"impersonate_user": False,
|
||||
"server_cert": None,
|
||||
@@ -912,121 +943,10 @@ class TestDatabaseApi(SupersetTestCase):
|
||||
url = "api/v1/database/test_connection"
|
||||
rv = self.post_assert_metric(url, data, "test_connection")
|
||||
|
||||
assert rv.status_code == 400
|
||||
assert rv.status_code == 422
|
||||
assert rv.headers["Content-Type"] == "application/json; charset=utf-8"
|
||||
response = json.loads(rv.data.decode("utf-8"))
|
||||
expected_response = {
|
||||
"errors": [
|
||||
{
|
||||
"message": 'Unable to resolve hostname "invalidhostname".',
|
||||
"error_type": "TEST_CONNECTION_INVALID_HOSTNAME_ERROR",
|
||||
"level": "error",
|
||||
"extra": {
|
||||
"hostname": "invalidhostname",
|
||||
"issue_codes": [
|
||||
{
|
||||
"code": 1007,
|
||||
"message": "Issue 1007 - The hostname provided can't be resolved.",
|
||||
}
|
||||
],
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
assert response == expected_response
|
||||
|
||||
@mock.patch("superset.databases.commands.test_connection.is_hostname_valid")
|
||||
@mock.patch("superset.databases.commands.test_connection.is_port_open")
|
||||
@mock.patch("superset.databases.commands.test_connection.is_host_up")
|
||||
def test_test_connection_failed_closed_port(
|
||||
self, mock_is_host_up, mock_is_port_open, mock_is_hostname_valid
|
||||
):
|
||||
"""
|
||||
Database API: Test test connection failed due to closed port.
|
||||
"""
|
||||
mock_is_hostname_valid.return_value = True
|
||||
mock_is_port_open.return_value = False
|
||||
mock_is_host_up.return_value = True
|
||||
|
||||
self.login("admin")
|
||||
data = {
|
||||
"sqlalchemy_uri": "postgres://username:password@localhost:12345/db",
|
||||
"database_name": "examples",
|
||||
"impersonate_user": False,
|
||||
"server_cert": None,
|
||||
}
|
||||
url = "api/v1/database/test_connection"
|
||||
rv = self.post_assert_metric(url, data, "test_connection")
|
||||
|
||||
assert rv.status_code == 400
|
||||
assert rv.headers["Content-Type"] == "application/json; charset=utf-8"
|
||||
response = json.loads(rv.data.decode("utf-8"))
|
||||
expected_response = {
|
||||
"errors": [
|
||||
{
|
||||
"message": "The host localhost is up, but the port 12345 is closed.",
|
||||
"error_type": "TEST_CONNECTION_PORT_CLOSED_ERROR",
|
||||
"level": "error",
|
||||
"extra": {
|
||||
"hostname": "localhost",
|
||||
"port": 12345,
|
||||
"issue_codes": [
|
||||
{
|
||||
"code": 1008,
|
||||
"message": "Issue 1008 - The port is closed.",
|
||||
}
|
||||
],
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
assert response == expected_response
|
||||
|
||||
@mock.patch("superset.databases.commands.test_connection.is_hostname_valid")
|
||||
@mock.patch("superset.databases.commands.test_connection.is_port_open")
|
||||
@mock.patch("superset.databases.commands.test_connection.is_host_up")
|
||||
def test_test_connection_failed_host_down(
|
||||
self, mock_is_host_up, mock_is_port_open, mock_is_hostname_valid
|
||||
):
|
||||
"""
|
||||
Database API: Test test connection failed due to host being down.
|
||||
"""
|
||||
mock_is_hostname_valid.return_value = True
|
||||
mock_is_port_open.return_value = False
|
||||
mock_is_host_up.return_value = False
|
||||
|
||||
self.login("admin")
|
||||
data = {
|
||||
"sqlalchemy_uri": "postgres://username:password@localhost:12345/db",
|
||||
"database_name": "examples",
|
||||
"impersonate_user": False,
|
||||
"server_cert": None,
|
||||
}
|
||||
url = "api/v1/database/test_connection"
|
||||
rv = self.post_assert_metric(url, data, "test_connection")
|
||||
|
||||
assert rv.status_code == 400
|
||||
assert rv.headers["Content-Type"] == "application/json; charset=utf-8"
|
||||
response = json.loads(rv.data.decode("utf-8"))
|
||||
expected_response = {
|
||||
"errors": [
|
||||
{
|
||||
"message": "The host localhost might be down, ond can't be reached on port 12345.",
|
||||
"error_type": "TEST_CONNECTION_HOST_DOWN_ERROR",
|
||||
"level": "error",
|
||||
"extra": {
|
||||
"hostname": "localhost",
|
||||
"port": 12345,
|
||||
"issue_codes": [
|
||||
{
|
||||
"code": 1009,
|
||||
"message": "Issue 1009 - The host might be down, and can't be reached on the provided port.",
|
||||
}
|
||||
],
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
expected_response = {"errors": [dataclasses.asdict(superset_error)]}
|
||||
assert response == expected_response
|
||||
|
||||
@pytest.mark.usefixtures(
|
||||
|
||||
Reference in New Issue
Block a user