diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse/api/api_schema/connection.py b/lib/dl_connector_clickhouse/dl_connector_clickhouse/api/api_schema/connection.py index 93de45cb4..e61272ce7 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse/api/api_schema/connection.py +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse/api/api_schema/connection.py @@ -1,6 +1,9 @@ from __future__ import annotations +from marshmallow import fields as ma_fields + from dl_api_connector.api_schema.connection_base import ConnectionMetaMixin +from dl_api_connector.api_schema.connection_base_fields import secret_string_field from dl_api_connector.api_schema.connection_mixins import ( DataExportForbiddenMixin, RawSQLLevelMixin, @@ -18,6 +21,14 @@ class ClickHouseConnectionSchema( TARGET_CLS = ConnectionClickhouse ALLOW_MULTI_HOST = True + username = ma_fields.String(attribute="data.username", allow_none=True, bi_extra=FieldExtra(editable=True)) + password = secret_string_field( + attribute="data.password", + required=False, + allow_none=True, + bi_extra=FieldExtra(editable=True), + ) + secure = core_ma_fields.OnOffField(attribute="data.secure", bi_extra=FieldExtra(editable=True)) ssl_ca = core_ma_fields.Base64StringField( attribute="data.ssl_ca", diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse/constants.py b/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse/constants.py index 95a6fa73b..d5a199b1b 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse/constants.py +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse/constants.py @@ -3,3 +3,5 @@ SOURCE_TYPE_CH_TABLE = DataSourceType.declare("CH_TABLE") SOURCE_TYPE_CH_SUBSELECT = DataSourceType.declare("CH_SUBSELECT") + +DEFAULT_CLICKHOUSE_USER = "default" diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse/testing/connection.py b/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse/testing/connection.py index 8fc4aa9ed..093b7e3e6 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse/testing/connection.py +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse/testing/connection.py @@ -16,8 +16,8 @@ def make_clickhouse_saved_connection( db_name: Optional[str], host: str, port: Optional[int], - username: Optional[str], - password: Optional[str], + username: Optional[str] = None, + password: Optional[str] = None, raw_sql_level: RawSQLLevel = RawSQLLevel.off, secure: bool = False, ssl_ca: Optional[str] = None, diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse/us_connection.py b/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse/us_connection.py index 0960b4cac..7af29b2e6 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse/us_connection.py +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse/us_connection.py @@ -6,9 +6,11 @@ from dl_i18n.localizer_base import Localizer from dl_connector_clickhouse.core.clickhouse.constants import ( + DEFAULT_CLICKHOUSE_USER, SOURCE_TYPE_CH_SUBSELECT, SOURCE_TYPE_CH_TABLE, ) +from dl_connector_clickhouse.core.clickhouse_base.dto import ClickHouseConnDTO from dl_connector_clickhouse.core.clickhouse_base.us_connection import ConnectionClickhouseBase @@ -27,6 +29,13 @@ class ConnectionClickhouse(ConnectionClickhouseBase): def get_data_source_template_templates(self, localizer: Localizer) -> list[DataSourceTemplate]: return self._make_subselect_templates(source_type=SOURCE_TYPE_CH_SUBSELECT, localizer=localizer) + def get_conn_dto(self) -> ClickHouseConnDTO: + base_dto = super().get_conn_dto() + return base_dto.clone( + username=base_dto.username or DEFAULT_CLICKHOUSE_USER, + password=base_dto.password or "", + ) + @property def allow_public_usage(self) -> bool: return True diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/api/base.py b/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/api/base.py index f73ed12c9..8bb966d6e 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/api/base.py +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/api/base.py @@ -35,6 +35,16 @@ def connection_params(self) -> dict: ) +class ClickHouseConnectionDefaultUserTestBase(ClickHouseConnectionTestBase): + @pytest.fixture(scope="class") + def connection_params(self) -> dict: + return dict( + db_name=CoreConnectionSettings.DB_NAME, + host=CoreConnectionSettings.HOST, + port=CoreConnectionSettings.PORT, + ) + + class ClickHouseDashSQLConnectionTest(ClickHouseConnectionTestBase): raw_sql_level = RawSQLLevel.dashsql diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/api/test_connection.py b/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/api/test_connection.py index c52e7ce8a..582548abc 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/api/test_connection.py +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/api/test_connection.py @@ -1,7 +1,14 @@ from dl_api_lib_testing.connector.connection_suite import DefaultConnectorConnectionTestSuite -from dl_connector_clickhouse_tests.db.api.base import ClickHouseConnectionTestBase +from dl_connector_clickhouse_tests.db.api.base import ( + ClickHouseConnectionDefaultUserTestBase, + ClickHouseConnectionTestBase, +) class TestClickHouseConnection(ClickHouseConnectionTestBase, DefaultConnectorConnectionTestSuite): pass + + +class TestClickHouseDefaultUserConnection(ClickHouseConnectionDefaultUserTestBase, DefaultConnectorConnectionTestSuite): + pass diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/core/base.py b/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/core/base.py index 4f5e45ca1..ae254134c 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/core/base.py +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/core/base.py @@ -58,6 +58,16 @@ def saved_connection( return conn +class BaseClickHouseDefaultUserTestClass(BaseClickHouseTestClass): + @pytest.fixture(scope="function") + def connection_creation_params(self) -> dict: + return dict( + db_name=test_config.CoreConnectionSettings.DB_NAME, + host=test_config.CoreConnectionSettings.HOST, + port=test_config.CoreConnectionSettings.PORT, + ) + + class BaseSslClickHouseTestClass(BaseClickHouseTestClass): @pytest.fixture(autouse=True) def clear_ssl_folder(self): diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/core/test_connection.py b/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/core/test_connection.py index 941e6d9ae..24cecdbfa 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/core/test_connection.py +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/core/test_connection.py @@ -7,8 +7,10 @@ from dl_core.us_connection_base import DataSourceTemplate from dl_core_testing.testcases.connection import DefaultConnectionTestClass +from dl_connector_clickhouse.core.clickhouse.constants import DEFAULT_CLICKHOUSE_USER from dl_connector_clickhouse.core.clickhouse.us_connection import ConnectionClickhouse from dl_connector_clickhouse_tests.db.core.base import ( + BaseClickHouseDefaultUserTestClass, BaseClickHouseTestClass, BaseSslClickHouseTestClass, ) @@ -42,6 +44,15 @@ def check_data_source_templates( assert "system" not in tmpl_db_names +class TestClickHouseDefaultUserConnection(BaseClickHouseDefaultUserTestClass, TestClickHouseConnection): + def check_saved_connection(self, conn: ConnectionClickhouse, params: dict) -> None: + assert conn.uuid is not None + assert conn.data.db_name == params["db_name"] + assert conn.data.username is None + assert conn.data.secure is False + assert conn.data.ssl_ca is None + + @pytest.mark.skipif(os.environ.get("WE_ARE_IN_CI"), reason="can't use localhost") class TestSslClickHouseConnection( BaseSslClickHouseTestClass, diff --git a/lib/dl_core/dl_core/connection_models/dto_defs.py b/lib/dl_core/dl_core/connection_models/dto_defs.py index 56c3b0f4e..1e0d82ff6 100644 --- a/lib/dl_core/dl_core/connection_models/dto_defs.py +++ b/lib/dl_core/dl_core/connection_models/dto_defs.py @@ -1,9 +1,10 @@ from __future__ import annotations from typing import ( + Any, ClassVar, - List, Optional, + TypeVar, ) import attr @@ -11,6 +12,9 @@ from dl_constants.enums import ConnectionType +_CONN_DTO_TV = TypeVar("_CONN_DTO_TV") + + @attr.s(frozen=True) class ConnDTO: conn_type: ClassVar[ConnectionType] @@ -22,6 +26,9 @@ def conn_reporting_data(self) -> dict: connection_id=self.conn_id, ) + def clone(self: _CONN_DTO_TV, **kwargs: Any) -> _CONN_DTO_TV: + return attr.evolve(self, **kwargs) + @attr.s(frozen=True) class DefaultSQLDTO(ConnDTO): # noqa @@ -32,7 +39,7 @@ class DefaultSQLDTO(ConnDTO): # noqa username: str = attr.ib(kw_only=True) password: str = attr.ib(repr=False, kw_only=True) - def get_all_hosts(self) -> List[str]: + def get_all_hosts(self) -> list[str]: return list(self.multihosts) if self.multihosts else [self.host] if self.host else [] def conn_reporting_data(self) -> dict: