From 17b92e725dd62ca722a40c374394c0b10d95e4b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9cile=20Vuilleumier?= Date: Thu, 14 Nov 2024 16:14:10 +0100 Subject: [PATCH] Add script to copy workspace --- README.md | 41 ++++++++++++++++--- geoservercloud/geoservercloud.py | 14 +++---- geoservercloud/geoservercloudsync.py | 61 ++++++++++++++++++++++++++++ pyproject.toml | 3 ++ tests/test_feature_type.py | 8 ++-- 5 files changed, 111 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index dbab246..8c6c6de 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,10 @@ pip install geoservercloud From git repository: ```shell +git clone https://github.com/camptocamp/python-geoservercloud +cd python-geoservercloud +python3 -m venv .venv +source .venv/bin/activate poetry install ``` @@ -38,8 +42,8 @@ For example, creating a workspace, connecting to a PostGIS datastore and publish ```python geoserver.create_workspace("example") geoserver.create_pg_datastore( - workspace="example", - datastore="example_store", + workspace_name="example", + datastore_name="example_store", pg_host="localhost", pg_port=5432, pg_db="database", @@ -47,9 +51,9 @@ geoserver.create_pg_datastore( pg_password="password" ) geoserver.create_feature_type( - layer="layer_example" - workspace="example", - datastore="example_store", + layer_name="layer_example", + workspace_name="example", + datastore_name="example_store", title={ "en":"Layer title", "fr": "Titre de la couche", @@ -93,3 +97,30 @@ def test_i18n_layer_title(geoserver, language, expected_title): layer = capabilities.get("Layer") assert layer.get("Title") == expected_title ``` + +### Syncing + +Copying a workspace from one GeoServer instance to another, including PG datastores, layers, styles and style images. + +#### In a Python console or script + +```python +from geoservercloud import GeoServerCloudSync +geoserversync = GeoServerCloudSync( + src_url="http://localhost:8080/geoserver", + src_user="admin", + src_password="geoserver", + dst_url="http://localhost:9099/geoserver", + dst_user="admin", + dst_password="geoserver", +) +geoserversync.copy_workspace("workspace_name", deep_copy=True) +``` + +#### In a shell terminal or script + +First install the package in your current virtual environment (see [Installation](#installation)), then run the script with: + +```shell +copy-workspace --src_url "http://localhost:8080/geoserver" --src_user admin --src_password geoserver --dst_url "http://localhost:9099/geoserver" --dst_user admin --dst_password geoserver --workspace workspace_name +``` diff --git a/geoservercloud/geoservercloud.py b/geoservercloud/geoservercloud.py index 340334c..d092c68 100644 --- a/geoservercloud/geoservercloud.py +++ b/geoservercloud/geoservercloud.py @@ -279,9 +279,9 @@ def get_feature_type( def create_feature_type( self, - layer: str, + layer_name: str, workspace_name: str | None = None, - datastore: str | None = None, + datastore_name: str | None = None, title: str | dict = "Default title", abstract: str | dict = "Default abstract", attributes: dict = Templates.geom_point_attribute(), # TODO: remove default value, because if should be None @@ -294,14 +294,14 @@ def create_feature_type( workspace_name = workspace_name or self.default_workspace if not workspace_name: raise ValueError("Workspace not provided") - datastore = datastore or self.default_datastore - if not datastore: + datastore_name = datastore_name or self.default_datastore + if not datastore_name: raise ValueError("Datastore not provided") feature_type = FeatureType( - name=layer, - native_name=layer, + name=layer_name, + native_name=layer_name, workspace_name=workspace_name, - store_name=datastore, + store_name=datastore_name, srs=f"EPSG:{epsg}", title=title, abstract=abstract, diff --git a/geoservercloud/geoservercloudsync.py b/geoservercloud/geoservercloudsync.py index 4d4839d..7f71241 100644 --- a/geoservercloud/geoservercloudsync.py +++ b/geoservercloud/geoservercloudsync.py @@ -1,3 +1,5 @@ +from argparse import ArgumentParser + from geoservercloud.models.resourcedirectory import ResourceDirectory from geoservercloud.services import RestService @@ -254,3 +256,62 @@ def copy_resource( @staticmethod def not_ok(http_status_code: int) -> bool: return http_status_code >= 400 + + +def parse_args(): + parser = ArgumentParser( + description=""" + Copy a workspace from a GeoServer instance to another, including PG datastores, + layers, styles and style images. + If using JNDI, the JNDI reference must exist in the destination GeoServer instance. + """ + ) + parser.add_argument( + "--src_url", + help="URL of the source GeoServer instance", + default="http://localhost:8080/geoserver", + ) + parser.add_argument( + "--src_user", + default="admin", + help="Admin user of the source GeoServer instance", + ) + parser.add_argument( + "--src_password", + default="geoserver", + help="Admin password of the source GeoServer instance", + ) + parser.add_argument( + "--dst_url", + help="URL of the destination GeoServer instance", + default="http://localhost:8080/geoserver", + ) + parser.add_argument( + "--dst_user", + default="admin", + help="Admin user of the destination GeoServer instance", + ) + parser.add_argument( + "--dst_password", + default="geoserver", + help="Admin password of the destination GeoServer instance", + ) + parser.add_argument( + "--workspace", + help="Workspace to copy", + ) + return parser.parse_args() + + +def main(): + args = parse_args() + geoserversync = GeoServerCloudSync( + args.src_url, + args.src_user, + args.src_password, + args.dst_url, + args.dst_user, + args.dst_password, + ) + content, code = geoserversync.copy_workspace(args.workspace, deep_copy=True) + print(code, content) diff --git a/pyproject.toml b/pyproject.toml index a88fd37..df4a41e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,6 +29,9 @@ requires = [ ] build-backend = "poetry.core.masonry.api" +[tool.poetry.scripts] +copy-workspace = "geoservercloud.geoservercloudsync:main" + [tool.poetry-dynamic-versioning] enable = true vcs = "git" diff --git a/tests/test_feature_type.py b/tests/test_feature_type.py index c36b307..a5e41b8 100644 --- a/tests/test_feature_type.py +++ b/tests/test_feature_type.py @@ -206,8 +206,8 @@ def test_create_feature_type( ) content, code = geoserver.create_feature_type( workspace_name=WORKSPACE, - datastore=STORE, - layer=LAYER, + datastore_name=STORE, + layer_name=LAYER, title={"en": "English"}, abstract={"en": "English"}, keywords=["example"], @@ -233,8 +233,8 @@ def test_update_feature_type( ) content, code = geoserver.create_feature_type( workspace_name=WORKSPACE, - datastore=STORE, - layer=LAYER, + datastore_name=STORE, + layer_name=LAYER, title={"en": "English"}, abstract={"en": "English"}, keywords=["example"],