From 6417fe70f4349fc863d119636334c3af98832d68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9cile=20Vuilleumier?= Date: Thu, 14 Nov 2024 14:12:12 +0100 Subject: [PATCH] Also copy style definition When copying a style SLD file, copy the style definition first, otherwise the style is name 'Default Styler' --- geoservercloud/geoservercloudsync.py | 10 ++++++++++ geoservercloud/services/restservice.py | 20 +++++++++++--------- tests/test_style.py | 18 ++++-------------- 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/geoservercloud/geoservercloudsync.py b/geoservercloud/geoservercloudsync.py index 6af3232..4d4839d 100644 --- a/geoservercloud/geoservercloudsync.py +++ b/geoservercloud/geoservercloudsync.py @@ -192,6 +192,16 @@ def copy_style( """ Copy a style from source to destination GeoServer instance """ + style_definition, status_code = self.src_instance.get_style_definition( + style_name, workspace_name + ) + if isinstance(style_definition, str): + return style_definition, status_code + content, status_code = self.dst_instance.create_style_definition( + style_name, style_definition, workspace_name + ) + if self.not_ok(status_code): + return content, status_code style, status_code = self.src_instance.get_style(style_name, workspace_name) if isinstance(style, str): return style, status_code diff --git a/geoservercloud/services/restservice.py b/geoservercloud/services/restservice.py index 49ad52c..7f69d83 100644 --- a/geoservercloud/services/restservice.py +++ b/geoservercloud/services/restservice.py @@ -345,7 +345,10 @@ def create_style_definition( ) data: bytes = style.xml_post_payload().encode() headers: dict[str, str] = {"Content-Type": "text/xml"} - if not self.resource_exists(resource_path): + # Use "Accept" header otherwise GeoServer throws a 500 on GET when the resource exists + if not self.resource_exists( + resource_path, headers={"Accept": "application/json"} + ): response: Response = self.rest_client.post(path, data=data, headers=headers) else: response = self.rest_client.put(resource_path, data=data, headers=headers) @@ -375,12 +378,11 @@ def create_style( headers = {"Content-Type": "application/vnd.ogc.sld+xml"} elif format == "zip": headers = {"Content-Type": "application/zip"} - if not self.resource_exists(resource_path): - response: Response = self.rest_client.post( - path, data=style, headers=headers - ) - else: - response = self.rest_client.put(resource_path, data=style, headers=headers) + # Do not check for existence because GeoServer throws a 500 if the style definition exists and not + # the SLD. Besides PUT is also supported on creation + response: Response = self.rest_client.put( + resource_path, data=style, headers=headers + ) return response.content.decode(), response.status_code def get_layer( @@ -614,8 +616,8 @@ def get_wmts_layer_bbox( except (KeyError, AttributeError): return None - def resource_exists(self, path: str) -> bool: - response: Response = self.rest_client.get(path) + def resource_exists(self, path: str, headers: dict[str, str] | None = None) -> bool: + response: Response = self.rest_client.get(path, headers=headers) return response.status_code == 200 @staticmethod diff --git a/tests/test_style.py b/tests/test_style.py index 4eb6b38..9e9c06a 100644 --- a/tests/test_style.py +++ b/tests/test_style.py @@ -2,6 +2,7 @@ import pytest import responses +import responses.matchers from requests import Response from geoservercloud import GeoServerCloud @@ -138,6 +139,7 @@ def test_create_style_definition(mocker, geoserver: GeoServerCloud) -> None: rsps.get( url=f"{geoserver.url}/rest/workspaces/test_workspace/styles/{STYLE}", status=404, + match=[responses.matchers.header_matcher({"Accept": "application/json"})], ) geoserver.create_style_definition( style_name=STYLE, filename="style.sld", workspace_name="test_workspace" @@ -152,12 +154,8 @@ def test_create_style_definition(mocker, geoserver: GeoServerCloud) -> None: def test_create_style_from_file(geoserver: GeoServerCloud) -> None: file_path = (Path(__file__).parent / "resources/style.sld").resolve() with responses.RequestsMock() as rsps: - rsps.get( + rsps.put( url=f"{geoserver.url}/rest/styles/{STYLE}.sld", - status=404, - ) - rsps.post( - url=f"{geoserver.url}/rest/styles", status=201, body=b"test_style", match=[ @@ -180,10 +178,6 @@ def test_create_style_from_file(geoserver: GeoServerCloud) -> None: def test_update_style_from_file(geoserver: GeoServerCloud) -> None: file_path = (Path(__file__).parent / "resources/style.sld").resolve() with responses.RequestsMock() as rsps: - rsps.get( - url=f"{geoserver.url}/rest/styles/{STYLE}.sld", - status=200, - ) rsps.put( url=f"{geoserver.url}/rest/styles/{STYLE}.sld", status=200, @@ -208,12 +202,8 @@ def test_update_style_from_file(geoserver: GeoServerCloud) -> None: def test_create_style_from_file_zip(geoserver: GeoServerCloud) -> None: file_path = (Path(__file__).parent / "resources/style.zip").resolve() with responses.RequestsMock() as rsps: - rsps.get( + rsps.put( url=f"{geoserver.url}/rest/styles/{STYLE}", - status=404, - ) - rsps.post( - url=f"{geoserver.url}/rest/styles", status=201, body=b"test_style", match=[