From ba809486e1a07fa52311a4e31ded041af14cbb8c Mon Sep 17 00:00:00 2001 From: Ilyas Gasanov Date: Tue, 12 Nov 2024 12:13:59 +0300 Subject: [PATCH 1/5] [DOP-19896] Add Clickhouse API schema --- README.rst | 1 + syncmaster/schemas/v1/connection_types.py | 2 + .../schemas/v1/connections/clickhouse.py | 47 ++++++ .../schemas/v1/connections/connection.py | 32 +++- syncmaster/schemas/v1/transfers/__init__.py | 7 + syncmaster/schemas/v1/transfers/db.py | 11 +- .../test_create_clickhouse_connection.py | 143 ++++++++++++++++++ 7 files changed, 239 insertions(+), 4 deletions(-) create mode 100644 syncmaster/schemas/v1/connections/clickhouse.py create mode 100644 tests/test_unit/test_connections/test_create_all_connection/test_create_clickhouse_connection.py diff --git a/README.rst b/README.rst index 0efa3dc0..a2a893a5 100644 --- a/README.rst +++ b/README.rst @@ -33,6 +33,7 @@ Data.SyncMaster is as low-code ETL tool for transfering data between databases a List of currently supported connections: * Apache Hive +* Clickhouse * Postgres * Oracle * HDFS diff --git a/syncmaster/schemas/v1/connection_types.py b/syncmaster/schemas/v1/connection_types.py index f4cd2af7..b8a11700 100644 --- a/syncmaster/schemas/v1/connection_types.py +++ b/syncmaster/schemas/v1/connection_types.py @@ -8,6 +8,7 @@ POSTGRES_TYPE = Literal["postgres"] S3_TYPE = Literal["s3"] HDFS_TYPE = Literal["hdfs"] +CLICKHOUSE_TYPE = Literal["clickhouse"] class ConnectionType(str, Enum): @@ -16,3 +17,4 @@ class ConnectionType(str, Enum): ORACLE = "oracle" S3 = "s3" HDFS = "hdfs" + CLICKHOUSE = "clickhouse" diff --git a/syncmaster/schemas/v1/connections/clickhouse.py b/syncmaster/schemas/v1/connections/clickhouse.py new file mode 100644 index 00000000..b4cf7320 --- /dev/null +++ b/syncmaster/schemas/v1/connections/clickhouse.py @@ -0,0 +1,47 @@ +# SPDX-FileCopyrightText: 2023-2024 MTS PJSC +# SPDX-License-Identifier: Apache-2.0 +from pydantic import BaseModel, Field, SecretStr + +from syncmaster.schemas.v1.connection_types import CLICKHOUSE_TYPE + + +class ClickhouseBaseSchema(BaseModel): + type: CLICKHOUSE_TYPE + + class Config: + from_attributes = True + + +class ReadClickhouseConnectionSchema(ClickhouseBaseSchema): + host: str + port: int + database: str | None = None + additional_params: dict = Field(default_factory=dict) + + +class ReadClickhouseAuthSchema(ClickhouseBaseSchema): + user: str + + +class UpdateClickhouseConnectionSchema(ClickhouseBaseSchema): + host: str | None = None + port: int | None = None + database: str | None = None + additional_params: dict | None = Field(default_factory=dict) + + +class UpdateClickhouseAuthSchema(ClickhouseBaseSchema): + user: str | None = None # noqa: F722 + password: SecretStr | None = None + + +class CreateClickhouseConnectionSchema(ClickhouseBaseSchema): + host: str + port: int + database: str | None = None + additional_params: dict = Field(default_factory=dict) + + +class CreateClickhouseAuthSchema(ClickhouseBaseSchema): + user: str + password: SecretStr diff --git a/syncmaster/schemas/v1/connections/connection.py b/syncmaster/schemas/v1/connections/connection.py index d2f48cc1..b9b86aaa 100644 --- a/syncmaster/schemas/v1/connections/connection.py +++ b/syncmaster/schemas/v1/connections/connection.py @@ -3,6 +3,14 @@ from pydantic import BaseModel, Field, model_validator +from syncmaster.schemas.v1.connections.clickhouse import ( + CreateClickhouseAuthSchema, + CreateClickhouseConnectionSchema, + ReadClickhouseAuthSchema, + ReadClickhouseConnectionSchema, + UpdateClickhouseAuthSchema, + UpdateClickhouseConnectionSchema, +) from syncmaster.schemas.v1.connections.hdfs import ( HDFSCreateAuthSchema, HDFSCreateConnectionSchema, @@ -51,12 +59,14 @@ | HDFSReadConnectionSchema | ReadOracleConnectionSchema | ReadPostgresConnectionSchema + | ReadClickhouseConnectionSchema | S3ReadConnectionSchema ) CreateConnectionDataSchema = ( CreateHiveConnectionSchema | CreateOracleConnectionSchema | CreatePostgresConnectionSchema + | CreateClickhouseConnectionSchema | HDFSCreateConnectionSchema | S3CreateConnectionSchema ) @@ -66,15 +76,31 @@ | S3UpdateConnectionSchema | UpdateOracleConnectionSchema | UpdatePostgresConnectionSchema + | UpdateClickhouseConnectionSchema ) ReadConnectionAuthDataSchema = ( - ReadHiveAuthSchema | ReadOracleAuthSchema | ReadPostgresAuthSchema | S3ReadAuthSchema | HDFSReadAuthSchema + ReadHiveAuthSchema + | ReadOracleAuthSchema + | ReadPostgresAuthSchema + | ReadClickhouseAuthSchema + | S3ReadAuthSchema + | HDFSReadAuthSchema ) CreateConnectionAuthDataSchema = ( - CreateHiveAuthSchema | CreateOracleAuthSchema | CreatePostgresAuthSchema | S3CreateAuthSchema | HDFSCreateAuthSchema + CreateHiveAuthSchema + | CreateOracleAuthSchema + | CreatePostgresAuthSchema + | CreateClickhouseAuthSchema + | S3CreateAuthSchema + | HDFSCreateAuthSchema ) UpdateConnectionAuthDataSchema = ( - UpdateHiveAuthSchema | UpdateOracleAuthSchema | UpdatePostgresAuthSchema | S3UpdateAuthSchema | HDFSUpdateAuthSchema + UpdateHiveAuthSchema + | UpdateOracleAuthSchema + | UpdatePostgresAuthSchema + | UpdateClickhouseAuthSchema + | S3UpdateAuthSchema + | HDFSUpdateAuthSchema ) diff --git a/syncmaster/schemas/v1/transfers/__init__.py b/syncmaster/schemas/v1/transfers/__init__.py index e87da765..d6c7d662 100644 --- a/syncmaster/schemas/v1/transfers/__init__.py +++ b/syncmaster/schemas/v1/transfers/__init__.py @@ -7,6 +7,7 @@ from syncmaster.schemas.v1.connections.connection import ReadConnectionSchema from syncmaster.schemas.v1.page import PageSchema from syncmaster.schemas.v1.transfers.db import ( + ClickhouseReadTransferSourceAndTarget, HiveReadTransferSourceAndTarget, OracleReadTransferSourceAndTarget, PostgresReadTransferSourceAndTarget, @@ -31,6 +32,7 @@ | HDFSReadTransferSource | HiveReadTransferSourceAndTarget | OracleReadTransferSourceAndTarget + | ClickhouseReadTransferSourceAndTarget | S3ReadTransferSource ) @@ -39,6 +41,7 @@ | HDFSReadTransferTarget | HiveReadTransferSourceAndTarget | OracleReadTransferSourceAndTarget + | ClickhouseReadTransferSourceAndTarget | S3ReadTransferTarget ) @@ -47,6 +50,7 @@ | HDFSCreateTransferSource | HiveReadTransferSourceAndTarget | OracleReadTransferSourceAndTarget + | ClickhouseReadTransferSourceAndTarget | S3CreateTransferSource ) @@ -55,6 +59,7 @@ | HDFSCreateTransferTarget | HiveReadTransferSourceAndTarget | OracleReadTransferSourceAndTarget + | ClickhouseReadTransferSourceAndTarget | S3CreateTransferTarget ) @@ -63,6 +68,7 @@ | HDFSReadTransferSource | HiveReadTransferSourceAndTarget | OracleReadTransferSourceAndTarget + | ClickhouseReadTransferSourceAndTarget | S3CreateTransferSource | None ) @@ -72,6 +78,7 @@ | HDFSReadTransferSource | HiveReadTransferSourceAndTarget | OracleReadTransferSourceAndTarget + | ClickhouseReadTransferSourceAndTarget | S3CreateTransferTarget | None ) diff --git a/syncmaster/schemas/v1/transfers/db.py b/syncmaster/schemas/v1/transfers/db.py index b3e24311..5618cb71 100644 --- a/syncmaster/schemas/v1/transfers/db.py +++ b/syncmaster/schemas/v1/transfers/db.py @@ -4,7 +4,12 @@ from pydantic import BaseModel -from syncmaster.schemas.v1.connection_types import HIVE_TYPE, ORACLE_TYPE, POSTGRES_TYPE +from syncmaster.schemas.v1.connection_types import ( + CLICKHOUSE_TYPE, + HIVE_TYPE, + ORACLE_TYPE, + POSTGRES_TYPE, +) class ReadDBTransfer(BaseModel): @@ -21,3 +26,7 @@ class OracleReadTransferSourceAndTarget(ReadDBTransfer): class PostgresReadTransferSourceAndTarget(ReadDBTransfer): type: POSTGRES_TYPE + + +class ClickhouseReadTransferSourceAndTarget(ReadDBTransfer): + type: CLICKHOUSE_TYPE diff --git a/tests/test_unit/test_connections/test_create_all_connection/test_create_clickhouse_connection.py b/tests/test_unit/test_connections/test_create_all_connection/test_create_clickhouse_connection.py new file mode 100644 index 00000000..d927af38 --- /dev/null +++ b/tests/test_unit/test_connections/test_create_all_connection/test_create_clickhouse_connection.py @@ -0,0 +1,143 @@ +import pytest +from httpx import AsyncClient +from sqlalchemy import select +from sqlalchemy.ext.asyncio import AsyncSession + +from syncmaster.db.models import AuthData, Connection +from syncmaster.db.repositories.utils import decrypt_auth_data +from syncmaster.settings import Settings +from tests.mocks import MockGroup, UserTestRoles + +pytestmark = [pytest.mark.asyncio, pytest.mark.backend, pytest.mark.clickhouse] + + +async def test_developer_plus_can_create_clickhouse_connection( + client: AsyncClient, + group: MockGroup, + session: AsyncSession, + settings: Settings, + role_developer_plus: UserTestRoles, +): + # Arrange + user = group.get_member_of_role(role_developer_plus) + + # Act + result = await client.post( + "v1/connections", + headers={"Authorization": f"Bearer {user.token}"}, + json={ + "group_id": group.id, + "name": "New connection", + "description": "", + "connection_data": { + "type": "clickhouse", + "host": "127.0.0.1", + "port": 1521, + "database": "database_name", + }, + "auth_data": { + "type": "clickhouse", + "user": "user", + "password": "secret", + }, + }, + ) + connection = ( + await session.scalars( + select(Connection).filter_by( + name="New connection", + ), + ) + ).first() + + creds = ( + await session.scalars( + select(AuthData).filter_by( + connection_id=connection.id, + ), + ) + ).one() + + # Assert + decrypted = decrypt_auth_data(creds.value, settings=settings) + assert result.status_code == 200 + assert result.json() == { + "id": connection.id, + "name": connection.name, + "description": connection.description, + "group_id": connection.group_id, + "connection_data": { + "type": connection.data["type"], + "host": connection.data["host"], + "port": connection.data["port"], + "database": connection.data["database"], + "additional_params": connection.data["additional_params"], + }, + "auth_data": { + "type": decrypted["type"], + "user": decrypted["user"], + }, + } + + +async def test_developer_plus_cannot_create_connection_with_type_mismatch( + client: AsyncClient, + group: MockGroup, + session: AsyncSession, + settings: Settings, + role_developer_plus: UserTestRoles, + event_loop, + request, +): + # Arrange + user = group.get_member_of_role(role_developer_plus) + + # Act + result = await client.post( + "v1/connections", + headers={"Authorization": f"Bearer {user.token}"}, + json={ + "group_id": group.id, + "name": "New connection", + "description": "", + "connection_data": { + "type": "postgres", + "host": "127.0.0.1", + "port": 5432, + "database_name": "postgres", + }, + "auth_data": { + "type": "clickhouse", + "user": "user", + "password": "secret", + }, + }, + ) + + # Assert + assert result.json() == { + "error": { + "code": "invalid_request", + "message": "Invalid request", + "details": [ + { + "context": {}, + "input": { + "group_id": group.id, + "name": "New connection", + "description": "", + "connection_data": { + "type": "postgres", + "host": "127.0.0.1", + "port": 5432, + "database_name": "postgres", + }, + "auth_data": {"type": "clickhouse", "user": "user", "password": "secret"}, + }, + "location": ["body"], + "message": "Value error, Connection data and auth data must have same types", + "code": "value_error", + }, + ], + }, + } From 6fa1625d6e3f1711f528769d40c813c687a40e11 Mon Sep 17 00:00:00 2001 From: Ilyas Gasanov Date: Tue, 12 Nov 2024 12:24:44 +0300 Subject: [PATCH 2/5] [DOP-19896] Add Clickhouse API schema --- docs/changelog/next_release/124.feature.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/changelog/next_release/124.feature.rst diff --git a/docs/changelog/next_release/124.feature.rst b/docs/changelog/next_release/124.feature.rst new file mode 100644 index 00000000..1d9e2158 --- /dev/null +++ b/docs/changelog/next_release/124.feature.rst @@ -0,0 +1 @@ +Add Clickhouse API schema \ No newline at end of file From eba7648c6960347a1ec391e73afb0aa1043894ce Mon Sep 17 00:00:00 2001 From: Ilyas Gasanov Date: Tue, 12 Nov 2024 12:40:19 +0300 Subject: [PATCH 3/5] [DOP-19896] Add Clickhouse API schema --- syncmaster/backend/api/v1/connections.py | 3 ++- tests/test_unit/test_connections/test_create_connection.py | 4 ++-- .../test_transfers/transfer_fixtures/transfers_fixture.py | 7 ++++++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/syncmaster/backend/api/v1/connections.py b/syncmaster/backend/api/v1/connections.py index a974abc5..47296f4d 100644 --- a/syncmaster/backend/api/v1/connections.py +++ b/syncmaster/backend/api/v1/connections.py @@ -18,6 +18,7 @@ from syncmaster.exceptions.credentials import AuthDataNotFoundError from syncmaster.exceptions.group import GroupNotFoundError from syncmaster.schemas.v1.connection_types import ( + CLICKHOUSE_TYPE, HDFS_TYPE, HIVE_TYPE, ORACLE_TYPE, @@ -37,7 +38,7 @@ router = APIRouter(tags=["Connections"], responses=get_error_responses()) -CONNECTION_TYPES = ORACLE_TYPE, POSTGRES_TYPE, HIVE_TYPE, S3_TYPE, HDFS_TYPE +CONNECTION_TYPES = ORACLE_TYPE, POSTGRES_TYPE, CLICKHOUSE_TYPE, HIVE_TYPE, S3_TYPE, HDFS_TYPE @router.get("/connections") diff --git a/tests/test_unit/test_connections/test_create_connection.py b/tests/test_unit/test_connections/test_create_connection.py index ac8422d4..e4439faf 100644 --- a/tests/test_unit/test_connections/test_create_connection.py +++ b/tests/test_unit/test_connections/test_create_connection.py @@ -282,7 +282,7 @@ async def test_check_fields_validation_on_create_connection( "context": { "discriminator": "'type'", "tag": "POSTGRESQL", - "expected_tags": "'hive', 'oracle', 'postgres', 'hdfs', 's3'", + "expected_tags": "'hive', 'oracle', 'postgres', 'clickhouse', 'hdfs', 's3'", }, "input": { "type": "POSTGRESQL", @@ -292,7 +292,7 @@ async def test_check_fields_validation_on_create_connection( "database_name": "postgres", }, "location": ["body", "connection_data"], - "message": "Input tag 'POSTGRESQL' found using 'type' does not match any of the expected tags: 'hive', 'oracle', 'postgres', 'hdfs', 's3'", + "message": "Input tag 'POSTGRESQL' found using 'type' does not match any of the expected tags: 'hive', 'oracle', 'postgres', 'clickhouse', 'hdfs', 's3'", "code": "union_tag_invalid", }, ], diff --git a/tests/test_unit/test_transfers/transfer_fixtures/transfers_fixture.py b/tests/test_unit/test_transfers/transfer_fixtures/transfers_fixture.py index 3ebf4809..17063024 100644 --- a/tests/test_unit/test_transfers/transfer_fixtures/transfers_fixture.py +++ b/tests/test_unit/test_transfers/transfer_fixtures/transfers_fixture.py @@ -76,7 +76,12 @@ async def group_transfers( source_params["directory_path"] = "/path/to/source" target_params.update(common_params) target_params["directory_path"] = "/path/to/target" - elif connection_type in [ConnectionType.HIVE, ConnectionType.POSTGRES, ConnectionType.ORACLE]: + elif connection_type in [ + ConnectionType.HIVE, + ConnectionType.POSTGRES, + ConnectionType.ORACLE, + ConnectionType.CLICKHOUSE, + ]: source_params["table_name"] = "source_table" target_params["table_name"] = "target_table" From 3565bf74a8191b843b44efd3eaf3d196cb97fc8f Mon Sep 17 00:00:00 2001 From: Ilyas Gasanov Date: Tue, 12 Nov 2024 12:53:23 +0300 Subject: [PATCH 4/5] [DOP-19896] Add Clickhouse API schema --- syncmaster/schemas/v1/connection_types.py | 4 +- .../test_create_clickhouse_connection.py | 65 +------------------ .../test_connections/test_read_connections.py | 4 +- .../test_transfers/test_create_transfer.py | 4 +- 4 files changed, 7 insertions(+), 70 deletions(-) diff --git a/syncmaster/schemas/v1/connection_types.py b/syncmaster/schemas/v1/connection_types.py index b8a11700..f21774d9 100644 --- a/syncmaster/schemas/v1/connection_types.py +++ b/syncmaster/schemas/v1/connection_types.py @@ -6,15 +6,15 @@ HIVE_TYPE = Literal["hive"] ORACLE_TYPE = Literal["oracle"] POSTGRES_TYPE = Literal["postgres"] +CLICKHOUSE_TYPE = Literal["clickhouse"] S3_TYPE = Literal["s3"] HDFS_TYPE = Literal["hdfs"] -CLICKHOUSE_TYPE = Literal["clickhouse"] class ConnectionType(str, Enum): POSTGRES = "postgres" HIVE = "hive" ORACLE = "oracle" + CLICKHOUSE = "clickhouse" S3 = "s3" HDFS = "hdfs" - CLICKHOUSE = "clickhouse" diff --git a/tests/test_unit/test_connections/test_create_all_connection/test_create_clickhouse_connection.py b/tests/test_unit/test_connections/test_create_all_connection/test_create_clickhouse_connection.py index d927af38..3caba257 100644 --- a/tests/test_unit/test_connections/test_create_all_connection/test_create_clickhouse_connection.py +++ b/tests/test_unit/test_connections/test_create_all_connection/test_create_clickhouse_connection.py @@ -32,7 +32,7 @@ async def test_developer_plus_can_create_clickhouse_connection( "connection_data": { "type": "clickhouse", "host": "127.0.0.1", - "port": 1521, + "port": 8123, "database": "database_name", }, "auth_data": { @@ -78,66 +78,3 @@ async def test_developer_plus_can_create_clickhouse_connection( "user": decrypted["user"], }, } - - -async def test_developer_plus_cannot_create_connection_with_type_mismatch( - client: AsyncClient, - group: MockGroup, - session: AsyncSession, - settings: Settings, - role_developer_plus: UserTestRoles, - event_loop, - request, -): - # Arrange - user = group.get_member_of_role(role_developer_plus) - - # Act - result = await client.post( - "v1/connections", - headers={"Authorization": f"Bearer {user.token}"}, - json={ - "group_id": group.id, - "name": "New connection", - "description": "", - "connection_data": { - "type": "postgres", - "host": "127.0.0.1", - "port": 5432, - "database_name": "postgres", - }, - "auth_data": { - "type": "clickhouse", - "user": "user", - "password": "secret", - }, - }, - ) - - # Assert - assert result.json() == { - "error": { - "code": "invalid_request", - "message": "Invalid request", - "details": [ - { - "context": {}, - "input": { - "group_id": group.id, - "name": "New connection", - "description": "", - "connection_data": { - "type": "postgres", - "host": "127.0.0.1", - "port": 5432, - "database_name": "postgres", - }, - "auth_data": {"type": "clickhouse", "user": "user", "password": "secret"}, - }, - "location": ["body"], - "message": "Value error, Connection data and auth data must have same types", - "code": "value_error", - }, - ], - }, - } diff --git a/tests/test_unit/test_connections/test_read_connections.py b/tests/test_unit/test_connections/test_read_connections.py index 487defa6..455a223a 100644 --- a/tests/test_unit/test_connections/test_read_connections.py +++ b/tests/test_unit/test_connections/test_read_connections.py @@ -307,10 +307,10 @@ async def test_search_connections_with_nonexistent_query( @pytest.mark.parametrize( "filter_params, expected_total", [ - ({}, 5), # No filters applied, expecting all connections + ({}, 6), # No filters applied, expecting all connections ({"type": ["oracle"]}, 1), ({"type": ["postgres", "hive"]}, 2), - ({"type": ["postgres", "hive", "oracle", "hdfs", "s3"]}, 5), + ({"type": ["postgres", "hive", "oracle", "clickhouse", "hdfs", "s3"]}, 6), ], ids=[ "no_filters", diff --git a/tests/test_unit/test_transfers/test_create_transfer.py b/tests/test_unit/test_transfers/test_create_transfer.py index b3056973..ae393f12 100644 --- a/tests/test_unit/test_transfers/test_create_transfer.py +++ b/tests/test_unit/test_transfers/test_create_transfer.py @@ -370,12 +370,12 @@ async def test_superuser_can_create_transfer( "location": ["body", "source_params"], "message": ( "Input tag 'new some connection type' found using 'type' " - "does not match any of the expected tags: 'postgres', 'hdfs', 'hive', 'oracle', 's3'" + "does not match any of the expected tags: 'postgres', 'hdfs', 'hive', 'oracle', 'clickhouse', 's3'" ), "code": "union_tag_invalid", "context": { "discriminator": "'type'", - "expected_tags": "'postgres', 'hdfs', 'hive', 'oracle', 's3'", + "expected_tags": "'postgres', 'hdfs', 'hive', 'oracle', 'clickhouse', 's3'", "tag": "new some connection type", }, "input": { From 088c880a84e9a1be0f04b661229a794071a23f1f Mon Sep 17 00:00:00 2001 From: Ilyas Gasanov Date: Tue, 12 Nov 2024 14:39:49 +0300 Subject: [PATCH 5/5] [DOP-19896] Add patch test for click schema --- .../__init__.py | 0 .../test_create_clickhouse_connection.py | 0 .../test_create_hdfs_connection.py | 0 .../test_create_hive_connection.py | 0 .../test_create_oracle_connection.py | 0 .../test_create_postgres_connection.py | 0 .../test_create_s3_connection.py | 0 .../test_update_clickhouse_connection.py | 71 +++++++++++++++++++ 8 files changed, 71 insertions(+) rename tests/test_unit/test_connections/{test_create_all_connection => test_db_connection}/__init__.py (100%) rename tests/test_unit/test_connections/{test_create_all_connection => test_db_connection}/test_create_clickhouse_connection.py (100%) rename tests/test_unit/test_connections/{test_create_all_connection => test_db_connection}/test_create_hdfs_connection.py (100%) rename tests/test_unit/test_connections/{test_create_all_connection => test_db_connection}/test_create_hive_connection.py (100%) rename tests/test_unit/test_connections/{test_create_all_connection => test_db_connection}/test_create_oracle_connection.py (100%) rename tests/test_unit/test_connections/{test_create_all_connection => test_db_connection}/test_create_postgres_connection.py (100%) rename tests/test_unit/test_connections/{test_create_all_connection => test_db_connection}/test_create_s3_connection.py (100%) create mode 100644 tests/test_unit/test_connections/test_db_connection/test_update_clickhouse_connection.py diff --git a/tests/test_unit/test_connections/test_create_all_connection/__init__.py b/tests/test_unit/test_connections/test_db_connection/__init__.py similarity index 100% rename from tests/test_unit/test_connections/test_create_all_connection/__init__.py rename to tests/test_unit/test_connections/test_db_connection/__init__.py diff --git a/tests/test_unit/test_connections/test_create_all_connection/test_create_clickhouse_connection.py b/tests/test_unit/test_connections/test_db_connection/test_create_clickhouse_connection.py similarity index 100% rename from tests/test_unit/test_connections/test_create_all_connection/test_create_clickhouse_connection.py rename to tests/test_unit/test_connections/test_db_connection/test_create_clickhouse_connection.py diff --git a/tests/test_unit/test_connections/test_create_all_connection/test_create_hdfs_connection.py b/tests/test_unit/test_connections/test_db_connection/test_create_hdfs_connection.py similarity index 100% rename from tests/test_unit/test_connections/test_create_all_connection/test_create_hdfs_connection.py rename to tests/test_unit/test_connections/test_db_connection/test_create_hdfs_connection.py diff --git a/tests/test_unit/test_connections/test_create_all_connection/test_create_hive_connection.py b/tests/test_unit/test_connections/test_db_connection/test_create_hive_connection.py similarity index 100% rename from tests/test_unit/test_connections/test_create_all_connection/test_create_hive_connection.py rename to tests/test_unit/test_connections/test_db_connection/test_create_hive_connection.py diff --git a/tests/test_unit/test_connections/test_create_all_connection/test_create_oracle_connection.py b/tests/test_unit/test_connections/test_db_connection/test_create_oracle_connection.py similarity index 100% rename from tests/test_unit/test_connections/test_create_all_connection/test_create_oracle_connection.py rename to tests/test_unit/test_connections/test_db_connection/test_create_oracle_connection.py diff --git a/tests/test_unit/test_connections/test_create_all_connection/test_create_postgres_connection.py b/tests/test_unit/test_connections/test_db_connection/test_create_postgres_connection.py similarity index 100% rename from tests/test_unit/test_connections/test_create_all_connection/test_create_postgres_connection.py rename to tests/test_unit/test_connections/test_db_connection/test_create_postgres_connection.py diff --git a/tests/test_unit/test_connections/test_create_all_connection/test_create_s3_connection.py b/tests/test_unit/test_connections/test_db_connection/test_create_s3_connection.py similarity index 100% rename from tests/test_unit/test_connections/test_create_all_connection/test_create_s3_connection.py rename to tests/test_unit/test_connections/test_db_connection/test_create_s3_connection.py diff --git a/tests/test_unit/test_connections/test_db_connection/test_update_clickhouse_connection.py b/tests/test_unit/test_connections/test_db_connection/test_update_clickhouse_connection.py new file mode 100644 index 00000000..41118110 --- /dev/null +++ b/tests/test_unit/test_connections/test_db_connection/test_update_clickhouse_connection.py @@ -0,0 +1,71 @@ +import pytest +from httpx import AsyncClient + +from tests.mocks import MockConnection, UserTestRoles + +pytestmark = [pytest.mark.asyncio, pytest.mark.backend, pytest.mark.clickhouse] + + +@pytest.mark.parametrize( + "create_connection_data,create_connection_auth_data", + [ + ( + { + "type": "clickhouse", + "host": "127.0.0.1", + "port": 8123, + }, + { + "type": "clickhouse", + "user": "user", + "password": "secret", + }, + ), + ], + indirect=True, +) +async def test_developer_plus_can_update_clickhouse_connection( + client: AsyncClient, + group_connection: MockConnection, + role_developer_plus: UserTestRoles, +): + # Arrange + user = group_connection.owner_group.get_member_of_role(role_developer_plus) + group_connection.connection.group.id + + # Act + result = await client.patch( + f"v1/connections/{group_connection.id}", + headers={"Authorization": f"Bearer {user.token}"}, + json={ + "connection_data": { + "type": "clickhouse", + "host": "127.0.1.1", + "database": "new_name", + }, + "auth_data": { + "type": "clickhouse", + "user": "new_user", + }, + }, + ) + + # Assert + assert result.status_code == 200 + assert result.json() == { + "id": group_connection.id, + "name": group_connection.name, + "description": group_connection.description, + "group_id": group_connection.group_id, + "connection_data": { + "type": group_connection.data["type"], + "host": "127.0.1.1", + "port": group_connection.data["port"], + "database": "new_name", + "additional_params": {}, + }, + "auth_data": { + "type": group_connection.credentials.value["type"], + "user": "new_user", + }, + }