From cb7670ac35ecae6ac57b81966f638beaad11daf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9cile=20Vuilleumier?= Date: Wed, 23 Oct 2024 08:15:19 +0200 Subject: [PATCH] Add facade class to copy GeoServer resources --- geoservercloud/__init__.py | 3 +- geoservercloud/geoservercloudsync.py | 51 ++++++++++++++++++++++++++ geoservercloud/services/restservice.py | 3 +- tests/test_sync.py | 41 +++++++++++++++++++++ 4 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 geoservercloud/geoservercloudsync.py create mode 100644 tests/test_sync.py diff --git a/geoservercloud/__init__.py b/geoservercloud/__init__.py index 3287872..61c623b 100644 --- a/geoservercloud/__init__.py +++ b/geoservercloud/__init__.py @@ -1,3 +1,4 @@ from .geoservercloud import GeoServerCloud +from .geoservercloudsync import GeoServerCloudSync -__all__: list[str] = ["GeoServerCloud"] +__all__: list[str] = ["GeoServerCloud", "GeoServerCloudSync"] diff --git a/geoservercloud/geoservercloudsync.py b/geoservercloud/geoservercloudsync.py new file mode 100644 index 0000000..768ed43 --- /dev/null +++ b/geoservercloud/geoservercloudsync.py @@ -0,0 +1,51 @@ +from geoservercloud.services import RestService + + +class GeoServerCloudSync: + """ + Facade class allowing synchronization of GeoServer resources between two GeoServer instances + + Attributes + ---------- + src_url : str + base GeoServer URL for source GeoServer instance + src_user : str + GeoServer username for source GeoServer instance + src_password : str + GeoServer password for source GeoServer instance + dst_url : str + base GeoServer URL for destination GeoServer instance + dst_user : str + GeoServer username for destination GeoServer instance + dst_password : str + GeoServer password for destination GeoServer instance + """ + + def __init__( + self, + src_url: str, + src_user: str, + src_password: str, + dst_url: str, + dst_user: str, + dst_password: str, + ) -> None: + self.src_url: str = src_url.strip("/") + self.src_user: str = src_user + self.src_password: str = src_password + self.src_auth: tuple[str, str] = (src_user, src_password) + self.src_instance: RestService = RestService(src_url, self.src_auth) + self.dst_url: str = dst_url.strip("/") + self.dst_user: str = dst_user + self.dst_password: str = dst_password + self.dst_auth: tuple[str, str] = (dst_user, dst_password) + self.dst_instance: RestService = RestService(dst_url, self.dst_auth) + + def copy_workspace(self, workspace_name: str) -> tuple[str, int]: + """ + Shallow copy a workspace from source to destination GeoServer instance + """ + workspace, status_code = self.src_instance.get_workspace(workspace_name) + if isinstance(workspace, str): + return workspace, status_code + return self.dst_instance.create_workspace(workspace) diff --git a/geoservercloud/services/restservice.py b/geoservercloud/services/restservice.py index 4ff6ec5..dd42554 100644 --- a/geoservercloud/services/restservice.py +++ b/geoservercloud/services/restservice.py @@ -582,8 +582,9 @@ def resource_exists(self, path: str) -> bool: response: Response = self.rest_client.get(path) return response.status_code == 200 + @staticmethod def deserialize_response( - self, response: Response, data_type: type[BaseModel] + response: Response, data_type: type[BaseModel] ) -> tuple[Any, int]: try: content = response.json() diff --git a/tests/test_sync.py b/tests/test_sync.py new file mode 100644 index 0000000..1534684 --- /dev/null +++ b/tests/test_sync.py @@ -0,0 +1,41 @@ +import pytest +import responses +from responses import matchers + +from geoservercloud import GeoServerCloudSync + +GEOSERVER_SRC_URL = "http://source-geoserver" +GEOSERVER_DST_URL = "http://destination-geoserver" + + +@pytest.fixture +def geoserver_sync(): + return GeoServerCloudSync( + GEOSERVER_SRC_URL, + "admin", + "geoserver", + GEOSERVER_DST_URL, + "admin", + "geoserver", + ) + + +def test_copy_workspace(geoserver_sync): + + workspace_name = "test_workspace" + workspace = {"name": workspace_name, "isolated": True} + + with responses.RequestsMock() as rsps: + rsps.get( + url=f"{GEOSERVER_SRC_URL}/rest/workspaces/{workspace_name}.json", + status=200, + json={"workspace": workspace}, + ) + rsps.post( + url=f"{GEOSERVER_DST_URL}/rest/workspaces.json", + status=201, + body=b"test_workspace", + match=[matchers.json_params_matcher({"workspace": workspace})], + ) + + assert geoserver_sync.copy_workspace(workspace_name) == (workspace_name, 201)