From 9631dbcc4d82f2d014d5d4b9348566b1829db086 Mon Sep 17 00:00:00 2001 From: juliarbkv Date: Fri, 8 Nov 2024 16:26:38 +0300 Subject: [PATCH] add clickhouse readonly 1 option support --- .../chs3_base/core/adapter.py | 1 - .../dl_connector_chyt/core/adapters.py | 1 - .../api/api_schema/connection.py | 1 + .../api/connection_form/form_config.py | 49 ++++++++++++++++-- .../core/clickhouse_base/adapters.py | 9 ++-- .../core/clickhouse_base/ch_commons.py | 9 ---- .../clickhouse_base/connection_executors.py | 1 + .../core/clickhouse_base/dto.py | 1 + .../core/clickhouse_base/exc.py | 5 +- .../storage_schemas/connection.py | 1 + .../core/clickhouse_base/target_dto.py | 1 + .../core/clickhouse_base/us_connection.py | 2 + .../en/LC_MESSAGES/dl_connector_clickhouse.mo | Bin 533 -> 586 bytes .../en/LC_MESSAGES/dl_connector_clickhouse.po | 3 ++ .../ru/LC_MESSAGES/dl_connector_clickhouse.mo | Bin 602 -> 655 bytes .../ru/LC_MESSAGES/dl_connector_clickhouse.po | 3 ++ .../db/api/base.py | 22 ++++++++ .../db/api/test_connection.py | 7 +++ .../db/api/test_data.py | 9 +++- .../db/api/test_dataset.py | 9 +++- .../db/config.py | 8 +++ .../db/core/base.py | 13 +++++ .../db/core/test_connection.py | 11 ++++ .../expected_forms/TenantCommon()_create.json | 48 +++++++++++++++++ .../expected_forms/TenantCommon()_edit.json | 48 +++++++++++++++++ .../docker-compose/db-clickhouse/users.xml | 14 +++++ 26 files changed, 256 insertions(+), 20 deletions(-) diff --git a/lib/dl_connector_bundle_chs3/dl_connector_bundle_chs3/chs3_base/core/adapter.py b/lib/dl_connector_bundle_chs3/dl_connector_bundle_chs3/chs3_base/core/adapter.py index 9b799119e..0a3c23377 100644 --- a/lib/dl_connector_bundle_chs3/dl_connector_bundle_chs3/chs3_base/core/adapter.py +++ b/lib/dl_connector_bundle_chs3/dl_connector_bundle_chs3/chs3_base/core/adapter.py @@ -41,7 +41,6 @@ def get_request_params(self, dba_q: DBAdapterQuery) -> dict[str, str]: database=dba_q.db_name or self._target_dto.db_name or "system", **get_ch_settings( read_only_level=2, - max_execution_time=self._target_dto.max_execution_time, ), ) diff --git a/lib/dl_connector_chyt/dl_connector_chyt/core/adapters.py b/lib/dl_connector_chyt/dl_connector_chyt/core/adapters.py index 5591fe6c0..cd531e629 100644 --- a/lib/dl_connector_chyt/dl_connector_chyt/core/adapters.py +++ b/lib/dl_connector_chyt/dl_connector_chyt/core/adapters.py @@ -70,7 +70,6 @@ def _get_dsn_params_from_headers(self) -> dict[str, str]: def get_ch_settings(self) -> dict: return get_ch_settings( - max_execution_time=self._target_dto.max_execution_time, read_only_level=2, output_format_json_quote_denormals=1, ) 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 e61272ce7..5c4ff732b 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 @@ -38,3 +38,4 @@ class ClickHouseConnectionSchema( load_default=None, load_only=True, ) + readonly = ma_fields.Integer(attribute="data.readonly", bi_extra=FieldExtra(editable=True)) diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse/api/connection_form/form_config.py b/lib/dl_connector_clickhouse/dl_connector_clickhouse/api/connection_form/form_config.py index 3f7062232..b9a7dcb24 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse/api/connection_form/form_config.py +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse/api/connection_form/form_config.py @@ -1,6 +1,10 @@ +from enum import unique import typing +import attr + from dl_api_commons.base_models import TenantDef +from dl_api_connector.form_config.models import rows as C from dl_api_connector.form_config.models.api_schema import ( FormActionApiSchema, FormApiSchema, @@ -12,16 +16,52 @@ ConnectionFormFactory, ConnectionFormMode, ) -from dl_api_connector.form_config.models.common import CommonFieldName -import dl_api_connector.form_config.models.rows as api_rows +from dl_api_connector.form_config.models.common import ( + CommonFieldName, + FormFieldName, +) from dl_api_connector.form_config.models.rows.base import FormRow from dl_api_connector.form_config.models.shortcuts.rows import RowConstructor from dl_configs.connectors_settings import ConnectorSettingsBase +from dl_i18n.localizer_base import Localizer from dl_connector_clickhouse.api.connection_info import ClickHouseConnectionInfoProvider from dl_connector_clickhouse.api.i18n.localizer import Translatable +@unique +class ClickHouseFieldName(FormFieldName): + readonly = "readonly" + + +@attr.s +class ClickHouseRowConstructor: + _localizer: Localizer = attr.ib() + + def readonly_mode_row(self) -> C.CustomizableRow: + return C.CustomizableRow( + items=[ + C.LabelRowItem( + align="start", + text=self._localizer.translate(Translatable("field_readonly-mode")), + display_conditions={CommonFieldName.advanced_settings: "opened"}, + ), + C.SelectRowItem( + name=ClickHouseFieldName.readonly, + width="s", + available_values=[ + C.SelectOption(content="0", value="0"), + C.SelectOption(content="1", value="1"), + C.SelectOption(content="2", value="2"), + ], + default_value="2", + control_props=C.SelectRowItem.Props(show_search=False), + display_conditions={CommonFieldName.advanced_settings: "opened"}, + ), + ] + ) + + class ClickHouseConnectionFormFactory(ConnectionFormFactory): DEFAULT_PORT = "8443" @@ -38,6 +78,7 @@ def get_common_api_schema_items() -> list[FormFieldApiSchema]: FormFieldApiSchema(name=CommonFieldName.secure), FormFieldApiSchema(name=CommonFieldName.ssl_ca), FormFieldApiSchema(name=CommonFieldName.data_export_forbidden), + FormFieldApiSchema(name=ClickHouseFieldName.readonly), ] def _get_edit_api_schema( @@ -109,8 +150,9 @@ def _get_common_section( rc: RowConstructor, connector_settings: ConnectorSettingsBase | None, ) -> typing.Sequence[FormRow]: + clickhouse_rc = ClickHouseRowConstructor(localizer=self._localizer) return [ - api_rows.CacheTTLRow(name=CommonFieldName.cache_ttl_sec), + C.CacheTTLRow(name=CommonFieldName.cache_ttl_sec), rc.raw_sql_level_row(), rc.collapse_advanced_settings_row(), *rc.ssl_rows( @@ -119,6 +161,7 @@ def _get_common_section( enabled_default_value=True, ), rc.data_export_forbidden_row(), + clickhouse_rc.readonly_mode_row(), ] def get_form_config( diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/adapters.py b/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/adapters.py index 034fb1652..ae4f35cdd 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/adapters.py +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/adapters.py @@ -140,7 +140,6 @@ def get_conn_line(self, db_name: Optional[str] = None, params: Optional[dict[str # TODO FIX: Move to utils def get_ch_settings(self) -> dict: return get_ch_settings( - max_execution_time=self._target_dto.max_execution_time, read_only_level=None, output_format_json_quote_denormals=1, ) @@ -401,13 +400,17 @@ def get_session_headers(self) -> dict[str, str]: } def get_request_params(self, dba_q: DBAdapterQuery) -> dict[str, str]: - read_only_level = None if dba_q.trusted_query else 2 + if dba_q.trusted_query: + read_only_level = None + elif self._target_dto.readonly == 1: + read_only_level = 1 + else: + read_only_level = 2 return dict( # TODO FIX: Move to utils database=dba_q.db_name or self._target_dto.db_name or "system", **get_ch_settings( read_only_level=read_only_level, - max_execution_time=self._target_dto.max_execution_time, ), ) diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/ch_commons.py b/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/ch_commons.py index 15e83b476..648eb8137 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/ch_commons.py +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/ch_commons.py @@ -41,7 +41,6 @@ def get_ch_settings( read_only_level: Optional[int] = None, - max_execution_time: Optional[int] = None, output_format_json_quote_denormals: Optional[int] = None, ) -> dict: settings = { @@ -49,14 +48,6 @@ def get_ch_settings( # 1 — JOIN behaves the same way as in standard SQL. # The type of the corresponding field is converted to Nullable, and empty cells are filled with NULL. "join_use_nulls": 1, - # https://clickhouse.com/docs/en/operations/settings/query-complexity#max-execution-time - # Maximum query execution time in seconds. - # By default, specify a large value to ensure there are no - # forever-running queries (which is also known to break old-version CH - # hosts at around 100_000 second long queries). - # Note that in CH the value is rounded down to integer, and 0 seems to mean 'no limit'. - # TODO: get rid of this parameter or figure out a proper way to use it, bc CH's estimates seem to be way off - "max_execution_time": max_execution_time if max_execution_time is None else 3600 * 4, "readonly": read_only_level, # request clickhouse stat in response headers # otherwise clickhouse sends nulls in X-ClickHouse-Summary diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/connection_executors.py b/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/connection_executors.py index 208c09505..04505a09b 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/connection_executors.py +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/connection_executors.py @@ -51,6 +51,7 @@ async def _make_target_conn_dto_pool(self) -> list[ClickHouseConnTargetDTO]: # secure=self._conn_dto.secure, ssl_ca=self._conn_dto.ssl_ca, ca_data=self._ca_data.decode("ascii"), + readonly=self._conn_dto.readonly, ) ) return dto_pool diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/dto.py b/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/dto.py index 9a9b6368c..75d5cbb25 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/dto.py +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/dto.py @@ -27,3 +27,4 @@ class ClickHouseConnDTO(ClickHouseBaseDTO, DefaultSQLDTO): # noqa # TODO CONSIDER: Is really optional endpoint: Optional[str] = attr.ib(kw_only=True) cluster_name: str = attr.ib(kw_only=True) + readonly: Optional[int] = attr.ib(kw_only=True, default=None) diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/exc.py b/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/exc.py index 16c14996d..e289618e9 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/exc.py +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/exc.py @@ -53,7 +53,10 @@ class CHIncorrectData(CHQueryError): class CHReadonlyUser(CHQueryError): err_code = CHQueryError.err_code + ["READONLY_USER"] - default_message = "Clickhouse user should have parameter readonly set to 0 or 2" + default_message = ( + "Clickhouse user must be correctly configured to use readonly 1 option (see docs). " + "For other readonly options user should have parameter readonly set to 0 or 2." + ) class EstimatedExecutionTooLong(exc.DatabaseQueryError): diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/storage_schemas/connection.py b/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/storage_schemas/connection.py index 5e3591b28..4c16c7b85 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/storage_schemas/connection.py +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/storage_schemas/connection.py @@ -22,3 +22,4 @@ class ConnectionClickHouseBaseDataStorageSchema( endpoint = ma_fields.String(required=False, allow_none=True, load_default=None, dump_default=None) cluster_name = ma_fields.String(required=False, allow_none=True, load_default=None, dump_default=None) max_execution_time = ma_fields.Integer(required=False, allow_none=True, load_default=None, dump_default=None) + readonly = ma_fields.Integer(required=False, allow_none=True, load_default=None, dump_default=None) diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/target_dto.py b/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/target_dto.py index 4334bda5c..29a2e5f9f 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/target_dto.py +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/target_dto.py @@ -20,6 +20,7 @@ class BaseClickHouseConnTargetDTO(BaseSQLConnTargetDTO, BaseAiohttpConnTargetDTO disable_value_processing: bool = attr.ib() secure: bool = attr.ib(kw_only=True, default=False) ssl_ca: Optional[str] = attr.ib(kw_only=True, default=None) + readonly: Optional[int] = attr.ib(kw_only=True, default=None) # TODO remove in the next release to avoid compatibility issues insert_quorum: Optional[int] = attr.ib(kw_only=True, default=None) diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/us_connection.py b/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/us_connection.py index 3c75c2f25..370cba4dd 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/us_connection.py +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse/core/clickhouse_base/us_connection.py @@ -54,6 +54,7 @@ class DataModel(ClassicConnectionSQL.DataModel): cluster_name: Optional[str] = attr.ib(default=None) max_execution_time: Optional[int] = attr.ib(default=None) ssl_ca: Optional[str] = attr.ib(kw_only=True, default=None) + readonly: Optional[int] = attr.ib(kw_only=True, default=None) def get_conn_dto(self) -> ClickHouseConnDTO: return ClickHouseConnDTO( @@ -69,6 +70,7 @@ def get_conn_dto(self) -> ClickHouseConnDTO: password=self.password, # type: ignore # 2024-01-24 # TODO: Argument "password" to "ClickHouseConnDTO" has incompatible type "str | None"; expected "str" [arg-type] secure=self.data.secure, ssl_ca=self.data.ssl_ca, + readonly=self.data.readonly, ) @staticmethod diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse/locales/en/LC_MESSAGES/dl_connector_clickhouse.mo b/lib/dl_connector_clickhouse/dl_connector_clickhouse/locales/en/LC_MESSAGES/dl_connector_clickhouse.mo index 0b1680d67bce0be1cd4cdb9c31378260cce39d8b..15a7061438c3d2a92dae27929fe9dd3cbd817b08 100644 GIT binary patch delta 179 zcmbQra*Cz?o)F7a1|VPsVi_QI0b+I_&H-W&=m26dAnpWWVIW=r#413%1&F19_$Cl< z2jVY443b~N$iTn>qz?e;QXqX2NOJ*cdnN`3Ad`Uwh(UHS12IsD4M+jO#9V3Nw9M3; fl=!05#FYHJoJ!r?{FKyK5b| Om2BM1%Q*QYVQVih3X0>n~4d=rSb z1MwFiRs!NRj0_AMK>9q8UJayg0BJ5D-NMAc0Aw<-05QleW*`O%u>mO{n3yXqoR*oI glM-K)nwXNGms6>mo1c=pv0a9dBM2%oc@g6d0Ku{xy8r+H delta 149 zcmeBYy~R?0Pl#nI0}!wPu?!H~05K~N#{e-16acXp5ElZm3J`Yyu@n%m1>)^Md;*A- zfVhE?fnha}UJRtUfV4jo0|SuB0Hhe0ffxipb}*!6rskx?C+B1)XX|FK5b| Om2BKB!#Mc{<8}ZT6Bf__ diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse/locales/ru/LC_MESSAGES/dl_connector_clickhouse.po b/lib/dl_connector_clickhouse/dl_connector_clickhouse/locales/ru/LC_MESSAGES/dl_connector_clickhouse.po index 4a2939dd6..59939ce83 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse/locales/ru/LC_MESSAGES/dl_connector_clickhouse.po +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse/locales/ru/LC_MESSAGES/dl_connector_clickhouse.po @@ -12,6 +12,9 @@ msgstr "" msgid "label_connector-clickhouse" msgstr "ClickHouse" +msgid "field_readonly-mode" +msgstr "Readonly" + msgid "field_click-house-port" msgstr "Порт HTTP-интерфейса" 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 8bb966d6e..6f426e125 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 @@ -11,6 +11,7 @@ from dl_connector_clickhouse_tests.db.config import ( API_TEST_CONFIG, CoreConnectionSettings, + CoreReadonlyConnectionSettings, ) from dl_connector_clickhouse_tests.db.core.base import BaseClickHouseTestClass @@ -45,6 +46,19 @@ def connection_params(self) -> dict: ) +class ClickHouseConnectionReadonlyUserTestBase(ClickHouseConnectionTestBase): + @pytest.fixture(scope="class") + def connection_params(self) -> dict: + return dict( + db_name=CoreReadonlyConnectionSettings.DB_NAME, + host=CoreReadonlyConnectionSettings.HOST, + port=CoreReadonlyConnectionSettings.PORT, + username=CoreReadonlyConnectionSettings.USERNAME, + password=CoreReadonlyConnectionSettings.PASSWORD, + readonly="1", + ) + + class ClickHouseDashSQLConnectionTest(ClickHouseConnectionTestBase): raw_sql_level = RawSQLLevel.dashsql @@ -61,5 +75,13 @@ def dataset_params(self, sample_table) -> dict: ) +class ClickHouseDatasetReadonlyUserTestBase(ClickHouseConnectionReadonlyUserTestBase, ClickHouseDatasetTestBase): + pass + + class ClickHouseDataApiTestBase(ClickHouseDatasetTestBase, StandardizedDataApiTestBase): mutation_caches_enabled = False + + +class ClickHouseDataApiReadonlyUserTestBase(ClickHouseDatasetReadonlyUserTestBase, StandardizedDataApiTestBase): + mutation_caches_enabled = False 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 582548abc..d283b5841 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 @@ -2,6 +2,7 @@ from dl_connector_clickhouse_tests.db.api.base import ( ClickHouseConnectionDefaultUserTestBase, + ClickHouseConnectionReadonlyUserTestBase, ClickHouseConnectionTestBase, ) @@ -12,3 +13,9 @@ class TestClickHouseConnection(ClickHouseConnectionTestBase, DefaultConnectorCon class TestClickHouseDefaultUserConnection(ClickHouseConnectionDefaultUserTestBase, DefaultConnectorConnectionTestSuite): pass + + +class TestClickHouseReadonlyUserConnection( + ClickHouseConnectionReadonlyUserTestBase, DefaultConnectorConnectionTestSuite +): + pass diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/api/test_data.py b/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/api/test_data.py index 075e5fb2d..dd8a86790 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/api/test_data.py +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/api/test_data.py @@ -7,7 +7,10 @@ DefaultConnectorDataResultTestSuite, ) -from dl_connector_clickhouse_tests.db.api.base import ClickHouseDataApiTestBase +from dl_connector_clickhouse_tests.db.api.base import ( + ClickHouseDataApiReadonlyUserTestBase, + ClickHouseDataApiTestBase, +) class TestClickHouseDataResult(ClickHouseDataApiTestBase, DefaultConnectorDataResultTestSuite): @@ -32,3 +35,7 @@ class TestClickHouseDataPreview(ClickHouseDataApiTestBase, DefaultConnectorDataP class TestClickHouseDataCache(ClickHouseDataApiTestBase, DefaultConnectorDataCacheTestSuite): data_caches_enabled = True + + +class TestClickHouseReadonlyUserDataResult(ClickHouseDataApiReadonlyUserTestBase, DefaultConnectorDataResultTestSuite): + pass diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/api/test_dataset.py b/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/api/test_dataset.py index c5670e586..ac573f7e3 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/api/test_dataset.py +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/api/test_dataset.py @@ -1,7 +1,14 @@ from dl_api_lib_testing.connector.dataset_suite import DefaultConnectorDatasetTestSuite -from dl_connector_clickhouse_tests.db.api.base import ClickHouseDatasetTestBase +from dl_connector_clickhouse_tests.db.api.base import ( + ClickHouseDatasetReadonlyUserTestBase, + ClickHouseDatasetTestBase, +) class TestClickHouseDataset(ClickHouseDatasetTestBase, DefaultConnectorDatasetTestSuite): pass + + +class TestClickHouseDatasetReadonlyUser(ClickHouseDatasetReadonlyUserTestBase, DefaultConnectorDatasetTestSuite): + pass diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/config.py b/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/config.py index b25ea904f..ff2044024 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/config.py +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/db/config.py @@ -52,6 +52,14 @@ class CoreSslConnectionSettings: PASSWORD: ClassVar[str] = "qwerty" +class CoreReadonlyConnectionSettings: + DB_NAME: ClassVar[str] = "test_data" + HOST: ClassVar[str] = get_test_container_hostport("db-clickhouse-22-10", fallback_port=52204).host + PORT: ClassVar[int] = get_test_container_hostport("db-clickhouse-22-10", fallback_port=52204).port + USERNAME: ClassVar[str] = "readonly" + PASSWORD: ClassVar[str] = "qwerty" + + DASHSQL_QUERY = r"""select arrayJoin([11, 22, NULL]) as a, [33, 44] as b, 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 ffff44eac..e772f4356 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 @@ -57,6 +57,19 @@ def connection_creation_params(self) -> dict: ) +class BaseClickHouseReadonlyUserTestClass(BaseClickHouseTestClass): + @pytest.fixture(scope="function") + def connection_creation_params(self) -> dict: + return dict( + db_name=test_config.CoreReadonlyConnectionSettings.DB_NAME, + host=test_config.CoreReadonlyConnectionSettings.HOST, + port=test_config.CoreReadonlyConnectionSettings.PORT, + username=test_config.CoreReadonlyConnectionSettings.USERNAME, + password=test_config.CoreReadonlyConnectionSettings.PASSWORD, + readonly="1", + ) + + 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 174c85402..d6753afb5 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 @@ -10,6 +10,7 @@ from dl_connector_clickhouse.core.clickhouse.us_connection import ConnectionClickhouse from dl_connector_clickhouse_tests.db.core.base import ( BaseClickHouseDefaultUserTestClass, + BaseClickHouseReadonlyUserTestClass, BaseClickHouseTestClass, BaseSslClickHouseTestClass, ) @@ -52,6 +53,16 @@ def check_saved_connection(self, conn: ConnectionClickhouse, params: dict) -> No assert conn.data.ssl_ca is None +class TestClickHouseReadonlyUserConnection(BaseClickHouseReadonlyUserTestClass, 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 == params["username"] + assert conn.data.secure is False + assert conn.data.ssl_ca is None + assert conn.data.readonly == "1" + + @pytest.mark.skipif(os.environ.get("WE_ARE_IN_CI"), reason="can't use localhost") class TestSslClickHouseConnection( BaseSslClickHouseTestClass, diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/unit/expected_forms/TenantCommon()_create.json b/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/unit/expected_forms/TenantCommon()_create.json index 7d60cd185..a1690582f 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/unit/expected_forms/TenantCommon()_create.json +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/unit/expected_forms/TenantCommon()_create.json @@ -186,6 +186,44 @@ ] } ] + }, + { + "items": [ + { + "id": "label", + "displayConditions": { + "advanced_settings": "opened" + }, + "text": "Readonly", + "align": "start" + }, + { + "id": "select", + "name": "readonly", + "displayConditions": { + "advanced_settings": "opened" + }, + "defaultValue": "2", + "width": "s", + "availableValues": [ + { + "content": "0", + "value": "0" + }, + { + "content": "1", + "value": "1" + }, + { + "content": "2", + "value": "2" + } + ], + "controlProps": { + "showSearch": false + } + } + ] } ], "apiSchema": { @@ -226,6 +264,11 @@ "required": false, "defaultAction": "include" }, + { + "name": "readonly", + "required": false, + "defaultAction": "include" + }, { "name": "cache_ttl_sec", "required": false, @@ -282,6 +325,11 @@ "required": false, "defaultAction": "include" }, + { + "name": "readonly", + "required": false, + "defaultAction": "include" + }, { "name": "type", "required": false, diff --git a/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/unit/expected_forms/TenantCommon()_edit.json b/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/unit/expected_forms/TenantCommon()_edit.json index 12c863c74..57b3b6cea 100644 --- a/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/unit/expected_forms/TenantCommon()_edit.json +++ b/lib/dl_connector_clickhouse/dl_connector_clickhouse_tests/unit/expected_forms/TenantCommon()_edit.json @@ -186,6 +186,44 @@ ] } ] + }, + { + "items": [ + { + "id": "label", + "displayConditions": { + "advanced_settings": "opened" + }, + "text": "Readonly", + "align": "start" + }, + { + "id": "select", + "name": "readonly", + "displayConditions": { + "advanced_settings": "opened" + }, + "defaultValue": "2", + "width": "s", + "availableValues": [ + { + "content": "0", + "value": "0" + }, + { + "content": "1", + "value": "1" + }, + { + "content": "2", + "value": "2" + } + ], + "controlProps": { + "showSearch": false + } + } + ] } ], "apiSchema": { @@ -226,6 +264,11 @@ "required": false, "defaultAction": "include" }, + { + "name": "readonly", + "required": false, + "defaultAction": "include" + }, { "name": "cache_ttl_sec", "required": false, @@ -276,6 +319,11 @@ "name": "data_export_forbidden", "required": false, "defaultAction": "include" + }, + { + "name": "readonly", + "required": false, + "defaultAction": "include" } ], "conditions": [] diff --git a/lib/dl_connector_clickhouse/docker-compose/db-clickhouse/users.xml b/lib/dl_connector_clickhouse/docker-compose/db-clickhouse/users.xml index ace4765b7..fffec99cc 100644 --- a/lib/dl_connector_clickhouse/docker-compose/db-clickhouse/users.xml +++ b/lib/dl_connector_clickhouse/docker-compose/db-clickhouse/users.xml @@ -5,6 +5,12 @@ 8 + + 1 + 1 + 0 + 1 + @@ -38,5 +44,13 @@ default default + + + ::/0 + + qwerty + readonly + default + \ No newline at end of file