geoservercloud 0.8.1.dev3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. geoservercloud-0.8.1.dev3/LICENSE +22 -0
  2. geoservercloud-0.8.1.dev3/PKG-INFO +166 -0
  3. geoservercloud-0.8.1.dev3/README.md +143 -0
  4. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/.gitignore +2 -0
  5. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/README.md +118 -0
  6. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/__init__.py +0 -0
  7. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/cli.py +40 -0
  8. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/compose/example.compose.yaml +37 -0
  9. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/compose/geodatabase/001_create_schemas.sql +3 -0
  10. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/config.py +82 -0
  11. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/data/sampledata.tgz +0 -0
  12. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/example.config.yaml +23 -0
  13. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/__init__.py +1 -0
  14. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/conftest.py +164 -0
  15. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/__init__.py +0 -0
  16. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/i18n/__init__.py +0 -0
  17. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/default_value/language_None_expected.png +0 -0
  18. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/default_value/language__expected.png +0 -0
  19. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/default_value/language_de_expected.png +0 -0
  20. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/default_value/language_fr_expected.png +0 -0
  21. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/default_value/language_it_expected.png +0 -0
  22. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/no_default_value/language_None_expected.png +0 -0
  23. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/no_default_value/language__expected.png +0 -0
  24. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/no_default_value/language_it_expected.png +0 -0
  25. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/default_value/language_None_expected.png +0 -0
  26. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/default_value/language__expected.png +0 -0
  27. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/default_value/language_de_expected.png +0 -0
  28. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/default_value/language_fr_expected.png +0 -0
  29. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/default_value/language_it_expected.png +0 -0
  30. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/no_default_value/language_None_expected.png +0 -0
  31. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/no_default_value/language__expected.png +0 -0
  32. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/no_default_value/language_it_expected.png +0 -0
  33. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/i18n/localized_labels.sld +36 -0
  34. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/i18n/localized_no_default.sld +37 -0
  35. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/i18n/localized_with_default.sld +37 -0
  36. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/wfs/__init__.py +0 -0
  37. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/wfs/wfs_delete_payload.xml +13 -0
  38. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/wfs/wfs_insert_payload.xml +16 -0
  39. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/wms/__init__.py +0 -0
  40. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/resources/wms/getmap_expected.png +0 -0
  41. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/test_cascaded_stores.py +122 -0
  42. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/test_cog.py +58 -0
  43. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/test_datastore.py +26 -0
  44. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/test_get_version.py +11 -0
  45. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/test_gwc.py +45 -0
  46. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/test_i18n.py +520 -0
  47. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/test_imagemosaic.py +510 -0
  48. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/test_imagemosaic_cog.py +208 -0
  49. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/test_wfs.py +87 -0
  50. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/test_wms.py +133 -0
  51. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/test_workspace.py +23 -0
  52. geoservercloud-0.8.1.dev3/geoserver_acceptance_tests/tests/utils.py +42 -0
  53. geoservercloud-0.8.1.dev3/geoservercloud/__init__.py +4 -0
  54. geoservercloud-0.8.1.dev3/geoservercloud/geoservercloud.py +1380 -0
  55. geoservercloud-0.8.1.dev3/geoservercloud/geoservercloudsync.py +357 -0
  56. geoservercloud-0.8.1.dev3/geoservercloud/gridsets/2056.xml +83 -0
  57. geoservercloud-0.8.1.dev3/geoservercloud/gridsets/21781.xml +83 -0
  58. geoservercloud-0.8.1.dev3/geoservercloud/gridsets/3857.xml +92 -0
  59. geoservercloud-0.8.1.dev3/geoservercloud/models/__init__.py +0 -0
  60. geoservercloud-0.8.1.dev3/geoservercloud/models/abstractlayer.py +92 -0
  61. geoservercloud-0.8.1.dev3/geoservercloud/models/common.py +376 -0
  62. geoservercloud-0.8.1.dev3/geoservercloud/models/coverage.py +127 -0
  63. geoservercloud-0.8.1.dev3/geoservercloud/models/coverages.py +19 -0
  64. geoservercloud-0.8.1.dev3/geoservercloud/models/coveragestore.py +89 -0
  65. geoservercloud-0.8.1.dev3/geoservercloud/models/datastore.py +84 -0
  66. geoservercloud-0.8.1.dev3/geoservercloud/models/datastores.py +6 -0
  67. geoservercloud-0.8.1.dev3/geoservercloud/models/featuretype.py +177 -0
  68. geoservercloud-0.8.1.dev3/geoservercloud/models/featuretypes.py +6 -0
  69. geoservercloud-0.8.1.dev3/geoservercloud/models/layer.py +78 -0
  70. geoservercloud-0.8.1.dev3/geoservercloud/models/layergroup.py +120 -0
  71. geoservercloud-0.8.1.dev3/geoservercloud/models/layergroups.py +6 -0
  72. geoservercloud-0.8.1.dev3/geoservercloud/models/resourcedirectory.py +44 -0
  73. geoservercloud-0.8.1.dev3/geoservercloud/models/style.py +138 -0
  74. geoservercloud-0.8.1.dev3/geoservercloud/models/styles.py +26 -0
  75. geoservercloud-0.8.1.dev3/geoservercloud/models/wmslayer.py +102 -0
  76. geoservercloud-0.8.1.dev3/geoservercloud/models/wmssettings.py +159 -0
  77. geoservercloud-0.8.1.dev3/geoservercloud/models/wmsstore.py +74 -0
  78. geoservercloud-0.8.1.dev3/geoservercloud/models/workspace.py +32 -0
  79. geoservercloud-0.8.1.dev3/geoservercloud/models/workspaces.py +6 -0
  80. geoservercloud-0.8.1.dev3/geoservercloud/services/__init__.py +7 -0
  81. geoservercloud-0.8.1.dev3/geoservercloud/services/owsservice.py +223 -0
  82. geoservercloud-0.8.1.dev3/geoservercloud/services/restclient.py +147 -0
  83. geoservercloud-0.8.1.dev3/geoservercloud/services/restlogger.py +5 -0
  84. geoservercloud-0.8.1.dev3/geoservercloud/services/restservice.py +1053 -0
  85. geoservercloud-0.8.1.dev3/geoservercloud/templates.py +84 -0
  86. geoservercloud-0.8.1.dev3/geoservercloud/utils.py +88 -0
  87. geoservercloud-0.8.1.dev3/pyproject.toml +61 -0
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2024, Camptocamp SA
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+ 2. Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+
13
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,166 @@
1
+ Metadata-Version: 2.3
2
+ Name: geoservercloud
3
+ Version: 0.8.1.dev3
4
+ Summary: Lightweight Python client to interact with GeoServer Cloud REST API, GeoServer ACL and OGC services
5
+ License: BSD-2-Clause
6
+ Author: Camptocamp
7
+ Author-email: info@camptocamp.com
8
+ Requires-Python: >=3.10
9
+ Classifier: License :: OSI Approved :: BSD License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Requires-Dist: OWSLib
16
+ Requires-Dist: psycopg2-binary
17
+ Requires-Dist: pytest
18
+ Requires-Dist: requests
19
+ Requires-Dist: sqlalchemy
20
+ Requires-Dist: xmltodict
21
+ Description-Content-Type: text/markdown
22
+
23
+ # python-geoservercloud
24
+
25
+ ## Documentation
26
+
27
+ https://camptocamp.github.io/python-geoservercloud/
28
+
29
+ ## Installation
30
+
31
+ From PyPI:
32
+
33
+ ```shell
34
+ pip install geoservercloud
35
+ ```
36
+
37
+ From git repository:
38
+
39
+ ```shell
40
+ git clone https://github.com/camptocamp/python-geoservercloud
41
+ cd python-geoservercloud
42
+ python3 -m venv .venv
43
+ source .venv/bin/activate
44
+ poetry install
45
+ ```
46
+
47
+ ## Quick start
48
+
49
+ ```python
50
+ from geoservercloud import GeoServerCloud
51
+
52
+ geoserver = GeoServerCloud(
53
+ url="http://localhost:9090/geoserver/cloud/",
54
+ user="admin",
55
+ password="geoserver",
56
+ )
57
+ geoserver.create_workspace("newworkspace")
58
+ ```
59
+
60
+ ## About
61
+
62
+ Lightweight Python client to interact with GeoServer Cloud REST API, GeoServer ACL and OGC services.
63
+ Intended use cases are listed below.
64
+
65
+ ### Programmatic setup of a GeoServer catalog
66
+
67
+ For example, creating a workspace, connecting to a PostGIS datastore and publishing a PG layer:
68
+
69
+ ```python
70
+ geoserver.create_workspace("example")
71
+ geoserver.create_pg_datastore(
72
+ workspace_name="example",
73
+ datastore_name="example_store",
74
+ pg_host="localhost",
75
+ pg_port=5432,
76
+ pg_db="database",
77
+ pg_user="user",
78
+ pg_password="password"
79
+ )
80
+ geoserver.create_feature_type(
81
+ layer_name="layer_example",
82
+ workspace_name="example",
83
+ datastore_name="example_store",
84
+ title={
85
+ "en":"Layer title",
86
+ "fr": "Titre de la couche",
87
+ "default": "Default title",
88
+ },
89
+ )
90
+ ```
91
+
92
+ ### Testing
93
+
94
+ Automatic tests of GeoServer functionalities with `pytest`, for example before upgrading.
95
+ The example below tests the fallback mechanism for internationalized layer titles in the GetCapabilities document.
96
+
97
+ ```python
98
+ @pytest.mark.parametrize(
99
+ "language,expected_title",
100
+ [
101
+ (
102
+ "en",
103
+ "Layer title",
104
+ ),
105
+ (
106
+ "fr",
107
+ "Titre de la couche",
108
+ ),
109
+ (
110
+ "de,en",
111
+ "Layer title",
112
+ ),
113
+ (
114
+ None,
115
+ "Default title",
116
+ ),
117
+ ],
118
+ )
119
+ def test_i18n_layer_title(geoserver, language, expected_title):
120
+ capabilities = geoserver.get_wms_layers(
121
+ workspace="example",
122
+ accept_languages=language,
123
+ )
124
+ layer = capabilities.get("Layer")
125
+ assert layer.get("Title") == expected_title
126
+ ```
127
+
128
+ A test suite is provided in the directory `geoserver_acceptance_tests`.
129
+
130
+ ### Syncing
131
+
132
+ Copying a workspace from one GeoServer instance to another, including PG datastores, layers, styles and style images.
133
+
134
+ #### In a Python console or script
135
+
136
+ ```python
137
+ from geoservercloud import GeoServerCloudSync
138
+ geoserversync = GeoServerCloudSync(
139
+ src_url="http://localhost:8080/geoserver",
140
+ src_user="admin",
141
+ src_password="geoserver",
142
+ dst_url="http://localhost:9099/geoserver",
143
+ dst_user="admin",
144
+ dst_password="geoserver",
145
+ )
146
+ geoserversync.copy_workspace("workspace_name", deep_copy=True)
147
+ ```
148
+
149
+ #### In a shell terminal or script
150
+
151
+ First install the package in your current virtual environment (see [Installation](#installation)), then run the script with:
152
+
153
+ ```shell
154
+ 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
155
+ ```
156
+
157
+ ### Logging
158
+
159
+ Set the log level using the standard `logging` module, e.g.:
160
+
161
+ ```python
162
+ import logging
163
+
164
+ logging.getLogger("geoservercloud").setLevel(logging.DEBUG)
165
+ ```
166
+
@@ -0,0 +1,143 @@
1
+ # python-geoservercloud
2
+
3
+ ## Documentation
4
+
5
+ https://camptocamp.github.io/python-geoservercloud/
6
+
7
+ ## Installation
8
+
9
+ From PyPI:
10
+
11
+ ```shell
12
+ pip install geoservercloud
13
+ ```
14
+
15
+ From git repository:
16
+
17
+ ```shell
18
+ git clone https://github.com/camptocamp/python-geoservercloud
19
+ cd python-geoservercloud
20
+ python3 -m venv .venv
21
+ source .venv/bin/activate
22
+ poetry install
23
+ ```
24
+
25
+ ## Quick start
26
+
27
+ ```python
28
+ from geoservercloud import GeoServerCloud
29
+
30
+ geoserver = GeoServerCloud(
31
+ url="http://localhost:9090/geoserver/cloud/",
32
+ user="admin",
33
+ password="geoserver",
34
+ )
35
+ geoserver.create_workspace("newworkspace")
36
+ ```
37
+
38
+ ## About
39
+
40
+ Lightweight Python client to interact with GeoServer Cloud REST API, GeoServer ACL and OGC services.
41
+ Intended use cases are listed below.
42
+
43
+ ### Programmatic setup of a GeoServer catalog
44
+
45
+ For example, creating a workspace, connecting to a PostGIS datastore and publishing a PG layer:
46
+
47
+ ```python
48
+ geoserver.create_workspace("example")
49
+ geoserver.create_pg_datastore(
50
+ workspace_name="example",
51
+ datastore_name="example_store",
52
+ pg_host="localhost",
53
+ pg_port=5432,
54
+ pg_db="database",
55
+ pg_user="user",
56
+ pg_password="password"
57
+ )
58
+ geoserver.create_feature_type(
59
+ layer_name="layer_example",
60
+ workspace_name="example",
61
+ datastore_name="example_store",
62
+ title={
63
+ "en":"Layer title",
64
+ "fr": "Titre de la couche",
65
+ "default": "Default title",
66
+ },
67
+ )
68
+ ```
69
+
70
+ ### Testing
71
+
72
+ Automatic tests of GeoServer functionalities with `pytest`, for example before upgrading.
73
+ The example below tests the fallback mechanism for internationalized layer titles in the GetCapabilities document.
74
+
75
+ ```python
76
+ @pytest.mark.parametrize(
77
+ "language,expected_title",
78
+ [
79
+ (
80
+ "en",
81
+ "Layer title",
82
+ ),
83
+ (
84
+ "fr",
85
+ "Titre de la couche",
86
+ ),
87
+ (
88
+ "de,en",
89
+ "Layer title",
90
+ ),
91
+ (
92
+ None,
93
+ "Default title",
94
+ ),
95
+ ],
96
+ )
97
+ def test_i18n_layer_title(geoserver, language, expected_title):
98
+ capabilities = geoserver.get_wms_layers(
99
+ workspace="example",
100
+ accept_languages=language,
101
+ )
102
+ layer = capabilities.get("Layer")
103
+ assert layer.get("Title") == expected_title
104
+ ```
105
+
106
+ A test suite is provided in the directory `geoserver_acceptance_tests`.
107
+
108
+ ### Syncing
109
+
110
+ Copying a workspace from one GeoServer instance to another, including PG datastores, layers, styles and style images.
111
+
112
+ #### In a Python console or script
113
+
114
+ ```python
115
+ from geoservercloud import GeoServerCloudSync
116
+ geoserversync = GeoServerCloudSync(
117
+ src_url="http://localhost:8080/geoserver",
118
+ src_user="admin",
119
+ src_password="geoserver",
120
+ dst_url="http://localhost:9099/geoserver",
121
+ dst_user="admin",
122
+ dst_password="geoserver",
123
+ )
124
+ geoserversync.copy_workspace("workspace_name", deep_copy=True)
125
+ ```
126
+
127
+ #### In a shell terminal or script
128
+
129
+ First install the package in your current virtual environment (see [Installation](#installation)), then run the script with:
130
+
131
+ ```shell
132
+ 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
133
+ ```
134
+
135
+ ### Logging
136
+
137
+ Set the log level using the standard `logging` module, e.g.:
138
+
139
+ ```python
140
+ import logging
141
+
142
+ logging.getLogger("geoservercloud").setLevel(logging.DEBUG)
143
+ ```
@@ -0,0 +1,2 @@
1
+ .venv
2
+ compose/geoserver_data/
@@ -0,0 +1,118 @@
1
+ # GeoServer acceptance test suite
2
+
3
+ ## Installation
4
+
5
+ The instructions below use `pip`, but it's also possible to use Poetry.
6
+
7
+ ### From PyPI
8
+
9
+ We recommend working in a dedicated Python virtual environment.
10
+ To create and activate it (on Linux):
11
+
12
+ ```shell
13
+ python -m venv .venv
14
+ source .venv/bin/activate
15
+ ```
16
+
17
+ Install the lib:
18
+
19
+ ```shell
20
+ pip install geoservercloud
21
+ ```
22
+
23
+ ### From local repository in development mode
24
+
25
+ ```shell
26
+ git clone git@github.com:camptocamp/python-geoservercloud
27
+ cd python-geoservercloud/geoserver_acceptance_tests
28
+ python -m venv .venv
29
+ source .venv/bin/activate
30
+ pip install -e ..
31
+ ```
32
+
33
+ ## Prerequisites
34
+
35
+ - a GeoServer instance is running and accessible with an admin user
36
+ - a test Postgres DB with the PostGIS extension is accessible
37
+ - the ImageMosaic sample data is mounted in GeoServer at `/opt/geoserver_data/sampledata`
38
+ - Internet access (from GeoServer)
39
+
40
+ The ImageMosaic sample data is provided as an archive at data/sampledata.tgz.
41
+ A script is provided to copy the sample data and is available in the venv once the package is installed:
42
+
43
+ ```shell
44
+ copy-test-data /example/path/
45
+ ```
46
+
47
+ And to directly extract the sample data to its destination:
48
+
49
+ ```shell
50
+ extract-test-data /example/path/
51
+ ```
52
+
53
+ ## Configuration
54
+
55
+ See example configuration file `example.config.yaml`. Most values can be overridden at run time through environment variables:
56
+
57
+ | Environment Variable | Description | Config Override |
58
+ | ----------------------------- | --------------------------------------------------- | ------------------- |
59
+ | `GEOSERVER_ACCEPTANCE_CONFIG` | Path to the config YAML file | (overrides default) |
60
+ | `GEOSERVER_URL` | GeoServer base URL | `server.url` |
61
+ | `GEOSERVER_VERIFYTLS` | Enable/disable TLS verification. Expects true/false | `server.verifytls` |
62
+ | `GEOSERVER_USER` | GeoServer admin username | `credentials.user` |
63
+ | `GEOSERVER_PASSWORD` | GeoServer admin password | `credentials.pass` |
64
+ | `GEOSERVER_PG_HOST_DOCKER` | PostgreSQL host from Docker container | `db.pg_host.docker` |
65
+ | `GEOSERVER_PG_PORT_DOCKER` | PostgreSQL port from Docker container | `db.pg_port.docker` |
66
+ | `GEOSERVER_PG_HOST_LOCAL` | PostgreSQL host from local host | `db.pg_host.local` |
67
+ | `GEOSERVER_PG_PORT_LOCAL` | PostgreSQL port from local host | `db.pg_port.local` |
68
+ | `GEOSERVER_PG_DB` | PostgreSQL database name | `db.pg_db` |
69
+ | `GEOSERVER_PG_USER` | PostgreSQL username | `db.pg_user` |
70
+ | `GEOSERVER_PG_PASSWORD` | PostgreSQL password | `db.pg_password` |
71
+ | `GEOSERVER_PG_SCHEMA` | PostgreSQL schema | `db.pg_schema` |
72
+
73
+ There are two separate settings for the DB host and port because typically GeoServer and the DB are run as a docker composition while the tests themselves are run from the host. Supported host platforms are Linux, MacOS (experimental) and Windows (experimental) - feedback and PRs are welcome.
74
+
75
+ ## Usage
76
+
77
+ Run tests
78
+
79
+ ```shell
80
+ pytest --pyargs geoserver_acceptance_tests.tests -v
81
+ ```
82
+
83
+ The default path to the configuration file is `/opt/geoserver_acceptance/config.yaml`. To change it - for example to use a file in the current directory, use the environment variable `GEOSERVER_ACCEPTANCE_CONFIG`:
84
+
85
+ ```shell
86
+ GEOSERVER_ACCEPTANCE_CONFIG=./config.yaml pytest --pyargs geoserver_acceptance_tests.tests -v
87
+ ```
88
+
89
+ ### Enabling and disabling tests
90
+
91
+ Certain kinds of tests can be enabled or disabled through environment variables:
92
+
93
+ | Environment Variable | Description | Default |
94
+ | ------------------------------------- | ------------------------------------------------------------- | ------- |
95
+ | `GEOSERVER_ACCEPTANCE_RUN_DB_TESTS` | Enable/disable tests requiring DB access | `true` |
96
+ | `GEOSERVER_ACCEPTANCE_RUN_SLOW_TESTS` | Enable/disable slow tests | `false` |
97
+ | `GEOSERVER_ACCEPTANCE_RUN_COG_TESTS` | Enable/disable COG tests | `false` |
98
+ | `GEOSERVER_ACCEPTANCE_RUN_JNDI_TESTS` | Enable/disable tests requiring a JNDI resource (jdbc/postgis) | `false` |
99
+
100
+ ### Run the example docker composition
101
+
102
+ An example docker composition is provided in order to illustrate the complete setup required to run the tests.
103
+ First, follow the steps described at [From local repository in development mode](#from-local-repository-in-development-mode).
104
+ Then run:
105
+
106
+ ```shell
107
+ extract-test-data ./compose/geoserver_data/
108
+ UID=$(id -u) docker compose -f compose/example.compose.yaml up -d
109
+ export GEOSERVER_ACCEPTANCE_CONFIG=./example.config.yaml
110
+ export GEOSERVER_ACCEPTANCE_RUN_JNDI_TESTS=true
111
+ pytest --pyargs geoserver_acceptance_tests.tests -v
112
+ ```
113
+
114
+ ### Image comparison tests
115
+
116
+ Some tests use image comparison. If such a test fails, the generated image will be persisted in a temporary directory created by pytest (check the test logs for the exact location). The temporary directory location can be overridden with the environment variable `GEOSERVER_ACCEPTANCE_FAILED_TESTS_DIR`.
117
+
118
+ This allows for visual comparison with the expected images which can be found in `tests/resources`.
@@ -0,0 +1,40 @@
1
+ import argparse
2
+ import shutil
3
+ from importlib import resources
4
+ from pathlib import Path
5
+
6
+
7
+ def copy_test_data():
8
+ parser = argparse.ArgumentParser(description="Copy GeoServer acceptance test data.")
9
+ parser.add_argument(
10
+ "target_dir",
11
+ help="Directory where test data should be copied",
12
+ )
13
+
14
+ args = parser.parse_args()
15
+ target = Path(args.target_dir)
16
+ target.mkdir(parents=True, exist_ok=True)
17
+
18
+ with resources.path("geoserver_acceptance_tests.data", "sampledata.tgz") as p:
19
+ shutil.copy(p, target / "sampledata.tgz")
20
+
21
+ print(f"Copied test data to: {target}")
22
+
23
+
24
+ def extract_test_data():
25
+ parser = argparse.ArgumentParser(
26
+ description="Extract GeoServer acceptance test data."
27
+ )
28
+ parser.add_argument(
29
+ "target_dir",
30
+ help="Directory where test data should be extracted",
31
+ )
32
+
33
+ args = parser.parse_args()
34
+ target = Path(args.target_dir)
35
+ target.mkdir(parents=True, exist_ok=True)
36
+
37
+ with resources.path("geoserver_acceptance_tests.data", "sampledata.tgz") as p:
38
+ shutil.unpack_archive(p, target)
39
+
40
+ print(f"Extracted test data to: {target}")
@@ -0,0 +1,37 @@
1
+ volumes:
2
+ geoserver_data:
3
+ driver: local
4
+ driver_opts:
5
+ type: none
6
+ o: bind
7
+ device: ./geoserver_data
8
+
9
+ services:
10
+ geoserver:
11
+ image: docker.osgeo.org/geoserver:2.28.x
12
+ ports:
13
+ - "8080:8080"
14
+ environment:
15
+ GEOSERVER_DATA_DIR: /opt/app/data_dir
16
+ RUN_WITH_USER_UID: ${UID}
17
+ CHANGE_OWNERSHIP_ON_FOLDERS: "/opt/app/data_dir /opt/geoserver_data"
18
+ POSTGRES_JNDI_ENABLED: true
19
+ POSTGRES_HOST: geodatabase
20
+ POSTGRES_PORT: 5432
21
+ POSTGRES_DB: geoserver
22
+ POSTGRES_USERNAME: geoserver
23
+ POSTGRES_PASSWORD: geoserver
24
+ POSTGRES_JNDI_RESOURCE_NAME: jdbc/postgis
25
+ volumes:
26
+ - geoserver_data:/opt/geoserver_data
27
+ geodatabase:
28
+ #image with arm/64 support:
29
+ image: imresamu/postgis:15-3.4
30
+ environment:
31
+ POSTGRES_DB: acceptance
32
+ POSTGRES_USER: geoserver
33
+ POSTGRES_PASSWORD: geoserver
34
+ volumes:
35
+ - ./geodatabase:/docker-entrypoint-initdb.d:ro
36
+ ports:
37
+ - "6432:5432"
@@ -0,0 +1,3 @@
1
+ \c acceptance
2
+ CREATE SCHEMA IF NOT EXISTS test1;
3
+ CREATE EXTENSION IF NOT EXISTS postgis;
@@ -0,0 +1,82 @@
1
+ import logging
2
+ import os
3
+
4
+ import yaml
5
+
6
+ DEFAULT_CONFIG_PATH = "/opt/geoserver_acceptance/config.yaml"
7
+
8
+
9
+ def load_config():
10
+ """Load test configuration from a YAML file.
11
+ Environment variables can be used to override specific configuration values."""
12
+ path = os.getenv("GEOSERVER_ACCEPTANCE_CONFIG", DEFAULT_CONFIG_PATH)
13
+
14
+ if not os.path.exists(path):
15
+ raise FileNotFoundError(f"Config file not found: {path}")
16
+
17
+ with open(path) as f:
18
+ config = yaml.safe_load(f)
19
+
20
+ # Environment variables have precedence over configuration file
21
+ override_url = os.getenv("GEOSERVER_URL")
22
+ if override_url:
23
+ config["server"]["url"] = override_url
24
+ override_verifytls = os.getenv("GEOSERVER_VERIFYTLS")
25
+ if override_verifytls is not None:
26
+ config["server"]["verifytls"] = override_verifytls.lower() == "true"
27
+ override_user = os.getenv("GEOSERVER_USER")
28
+ if override_user:
29
+ config["credentials"]["user"] = override_user
30
+ override_pass = os.getenv("GEOSERVER_PASSWORD")
31
+ if override_pass:
32
+ config["credentials"]["pass"] = override_pass
33
+ override_pg_host = os.getenv("GEOSERVER_PG_HOST_DOCKER")
34
+ if override_pg_host:
35
+ config["db"]["pg_host"]["docker"] = override_pg_host
36
+ override_pg_port = os.getenv("GEOSERVER_PG_PORT_DOCKER")
37
+ if override_pg_port:
38
+ config["db"]["pg_port"]["docker"] = int(override_pg_port)
39
+ override_pg_host = os.getenv("GEOSERVER_PG_HOST_LOCAL")
40
+ if override_pg_host:
41
+ config["db"]["pg_host"]["local"] = override_pg_host
42
+ override_pg_port = os.getenv("GEOSERVER_PG_PORT_LOCAL")
43
+ if override_pg_port:
44
+ config["db"]["pg_port"]["local"] = int(override_pg_port)
45
+ override_pg_db = os.getenv("GEOSERVER_PG_DB")
46
+ if override_pg_db:
47
+ config["db"]["pg_db"] = override_pg_db
48
+ override_pg_user = os.getenv("GEOSERVER_PG_USER")
49
+ if override_pg_user:
50
+ config["db"]["pg_user"] = override_pg_user
51
+ override_pg_password = os.getenv("GEOSERVER_PG_PASSWORD")
52
+ if override_pg_password:
53
+ config["db"]["pg_password"] = override_pg_password
54
+ override_pg_schema = os.getenv("GEOSERVER_PG_SCHEMA")
55
+ if override_pg_schema:
56
+ config["db"]["pg_schema"] = override_pg_schema
57
+
58
+ # Configure logging for geoservercloud library
59
+ _setup_logging(config)
60
+
61
+ return config
62
+
63
+
64
+ def _setup_logging(config: dict):
65
+ """Set up logging for the geoservercloud library based on configuration."""
66
+ # Get logging configuration from config file or use defaults
67
+ log_config = config.get("logging", {})
68
+ log_level_str = log_config.get("level", "INFO").upper()
69
+ log_level = getattr(logging, log_level_str, logging.INFO)
70
+ log_format = log_config.get(
71
+ "format", "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
72
+ )
73
+
74
+ # Configure the geoservercloud logger
75
+ logger = logging.getLogger("geoservercloud")
76
+ logger.setLevel(log_level)
77
+
78
+ # Add console handler if not already present
79
+ if not logger.handlers:
80
+ handler = logging.StreamHandler()
81
+ handler.setFormatter(logging.Formatter(log_format))
82
+ logger.addHandler(handler)
@@ -0,0 +1,23 @@
1
+ server:
2
+ url: "http://localhost:8080/geoserver"
3
+ verifytls: true
4
+
5
+ credentials:
6
+ user: "admin"
7
+ pass: "geoserver"
8
+
9
+ logging:
10
+ level: "DEBUG"
11
+ format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
12
+
13
+ db:
14
+ pg_host:
15
+ docker: "geodatabase"
16
+ local: "localhost"
17
+ pg_port:
18
+ docker: 5432
19
+ local: 6432
20
+ pg_db: "acceptance"
21
+ pg_user: "geoserver"
22
+ pg_password: "geoserver"
23
+ pg_schema: "test1"