geoservercloud 0.8.10.dev6__tar.gz → 0.8.11.dev1__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.
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/PKG-INFO +1 -1
- geoservercloud-0.8.11.dev1/geoserver_acceptance_tests/tests/test_gwc.py +295 -0
- geoservercloud-0.8.11.dev1/geoserver_acceptance_tests/tests/test_rest_resource.py +110 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/pyproject.toml +1 -1
- geoservercloud-0.8.10.dev6/geoserver_acceptance_tests/tests/test_gwc.py +0 -45
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/LICENSE +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/README.md +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/.gitignore +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/README.md +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/__init__.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/ci.config.yaml +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/cli.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/compose/ci.compose.yaml +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/compose/example.compose.yaml +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/compose/geodatabase/001_create_schemas.sql +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/config.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/data/sampledata.tgz +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/example.config.yaml +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/__init__.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/conftest.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/__init__.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/i18n/__init__.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/default_value/language_None_expected.png +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/default_value/language__expected.png +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/default_value/language_de_expected.png +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/default_value/language_fr_expected.png +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/default_value/language_it_expected.png +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/no_default_value/language_None_expected.png +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/no_default_value/language__expected.png +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/no_default_value/language_it_expected.png +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/default_value/language_None_expected.png +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/default_value/language__expected.png +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/default_value/language_de_expected.png +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/default_value/language_fr_expected.png +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/default_value/language_it_expected.png +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/no_default_value/language_None_expected.png +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/no_default_value/language__expected.png +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/no_default_value/language_it_expected.png +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/i18n/localized_labels.sld +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/i18n/localized_no_default.sld +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/i18n/localized_with_default.sld +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/wfs/__init__.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/wfs/wfs_delete_payload.xml +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/wfs/wfs_insert_payload.xml +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/wms/__init__.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/resources/wms/getmap_expected.png +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/test_cascaded_stores.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/test_cog.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/test_datastore.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/test_get_version.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/test_i18n.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/test_imagemosaic.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/test_imagemosaic_cog.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/test_installed_fonts.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/test_ogcapi_features.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/test_s3_credentials_chain.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/test_wfs.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/test_wms.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/test_workspace.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/utils.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/__init__.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/geoservercloud.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/geoservercloudsync.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/gridsets/2056.xml +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/gridsets/21781.xml +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/gridsets/3857.xml +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/__init__.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/abstractlayer.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/common.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/coverage.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/coverages.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/coveragestore.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/datastore.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/datastores.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/featuretype.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/featuretypes.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/gwclayer.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/layer.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/layergroup.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/layergroups.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/resourcedirectory.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/s3blobstore.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/style.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/styles.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/wmslayer.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/wmssettings.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/wmsstore.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/wmtsstore.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/workspace.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/workspaces.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/services/__init__.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/services/owsservice.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/services/restclient.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/services/restlogger.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/services/restservice.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/templates.py +0 -0
- {geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/utils.py +0 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import time
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from geoservercloud import GeoServerCloud
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_tile_cache(geoserver_factory):
|
|
9
|
+
workspace = "test_gwc"
|
|
10
|
+
wmts_store = "test_gwc_store"
|
|
11
|
+
wmts_layer = "ch.swisstopo.swissimage"
|
|
12
|
+
geoserver: GeoServerCloud = geoserver_factory(workspace)
|
|
13
|
+
|
|
14
|
+
content, status = geoserver.create_wmts_store(
|
|
15
|
+
workspace,
|
|
16
|
+
wmts_store,
|
|
17
|
+
capabilities="https://wmts.geo.admin.ch/EPSG/4326/1.0.0/WMTSCapabilities.xml",
|
|
18
|
+
)
|
|
19
|
+
assert status == 201
|
|
20
|
+
assert content == wmts_store
|
|
21
|
+
|
|
22
|
+
content, status = geoserver.create_wmts_layer(workspace, wmts_store, wmts_layer)
|
|
23
|
+
assert status == 201
|
|
24
|
+
assert content == wmts_layer
|
|
25
|
+
|
|
26
|
+
# with automatic tile caching enabled the tile layer is created with the
|
|
27
|
+
# WMTS layer; wait for it before publishing over it, GeoServer Cloud
|
|
28
|
+
# propagates the new layer between services asynchronously
|
|
29
|
+
assert wait_for_tile_layer_status(geoserver, workspace, wmts_layer, 200) == 200
|
|
30
|
+
|
|
31
|
+
content, status = geoserver.publish_gwc_layer(workspace, wmts_layer)
|
|
32
|
+
assert status == 200
|
|
33
|
+
assert content in ["", "layer saved"]
|
|
34
|
+
|
|
35
|
+
response = geoserver.get_tile(
|
|
36
|
+
format="image/png",
|
|
37
|
+
layer=f"{workspace}:{wmts_layer}",
|
|
38
|
+
tile_matrix_set="EPSG:4326",
|
|
39
|
+
tile_matrix="EPSG:4326:9",
|
|
40
|
+
row=122,
|
|
41
|
+
column=534,
|
|
42
|
+
)
|
|
43
|
+
assert response.info().get("Content-Type") == "image/png"
|
|
44
|
+
assert response.info().get("Geowebcache-Cache-Result") == "MISS"
|
|
45
|
+
|
|
46
|
+
response = geoserver.get_tile(
|
|
47
|
+
format="image/png",
|
|
48
|
+
layer=f"{workspace}:{wmts_layer}",
|
|
49
|
+
tile_matrix_set="EPSG:4326",
|
|
50
|
+
tile_matrix="EPSG:4326:9",
|
|
51
|
+
row=122,
|
|
52
|
+
column=534,
|
|
53
|
+
)
|
|
54
|
+
assert response.info().get("Geowebcache-Cache-Result") == "HIT"
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def wait_for_tile_layer_status(
|
|
58
|
+
geoserver, workspace, layer, expected_status, timeout=30
|
|
59
|
+
):
|
|
60
|
+
"""Poll the GWC REST API until the tile layer reaches the expected status.
|
|
61
|
+
|
|
62
|
+
GeoServer Cloud propagates catalog changes between services asynchronously;
|
|
63
|
+
against a monolithic GeoServer the first poll already settles.
|
|
64
|
+
"""
|
|
65
|
+
deadline = time.monotonic() + timeout
|
|
66
|
+
status = None
|
|
67
|
+
while time.monotonic() < deadline:
|
|
68
|
+
_, status = geoserver.get_gwc_layer(workspace, layer)
|
|
69
|
+
if status == expected_status:
|
|
70
|
+
return status
|
|
71
|
+
time.sleep(0.5)
|
|
72
|
+
return status
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@pytest.mark.db
|
|
76
|
+
def test_automatic_tile_layer_lifecycle(config, geoserver_factory):
|
|
77
|
+
"""Tile layers must follow REST catalog changes when automatic caching is on.
|
|
78
|
+
|
|
79
|
+
Regression test for https://github.com/geoserver/geoserver-cloud/issues/519
|
|
80
|
+
"""
|
|
81
|
+
workspace = datastore = "test_gwc_auto"
|
|
82
|
+
feature_type = "auto_cached_layer"
|
|
83
|
+
renamed = "auto_cached_layer_renamed"
|
|
84
|
+
geoserver: GeoServerCloud = geoserver_factory(workspace)
|
|
85
|
+
|
|
86
|
+
_, code = geoserver.create_pg_datastore(
|
|
87
|
+
workspace_name=workspace,
|
|
88
|
+
datastore_name=datastore,
|
|
89
|
+
pg_host=config["db"]["pg_host"]["docker"],
|
|
90
|
+
pg_port=config["db"]["pg_port"]["docker"],
|
|
91
|
+
pg_db=config["db"]["pg_db"],
|
|
92
|
+
pg_user=config["db"]["pg_user"],
|
|
93
|
+
pg_password=config["db"]["pg_password"],
|
|
94
|
+
pg_schema=config["db"]["pg_schema"],
|
|
95
|
+
set_default_datastore=True,
|
|
96
|
+
)
|
|
97
|
+
assert code == 201
|
|
98
|
+
|
|
99
|
+
attributes = {
|
|
100
|
+
"geom": {"type": "Point", "required": True},
|
|
101
|
+
"id": {"type": "integer", "required": True},
|
|
102
|
+
}
|
|
103
|
+
_, code = geoserver.create_feature_type(
|
|
104
|
+
feature_type, attributes=attributes, epsg=4326, workspace_name=workspace
|
|
105
|
+
)
|
|
106
|
+
assert code == 201
|
|
107
|
+
|
|
108
|
+
assert wait_for_tile_layer_status(geoserver, workspace, feature_type, 200) == 200
|
|
109
|
+
|
|
110
|
+
response = geoserver.rest_service.rest_client.put(
|
|
111
|
+
f"/rest/workspaces/{workspace}/datastores/{datastore}/featuretypes/{feature_type}.json",
|
|
112
|
+
json={"featureType": {"name": renamed}},
|
|
113
|
+
)
|
|
114
|
+
assert response.status_code == 200
|
|
115
|
+
|
|
116
|
+
assert wait_for_tile_layer_status(geoserver, workspace, renamed, 200) == 200
|
|
117
|
+
assert wait_for_tile_layer_status(geoserver, workspace, feature_type, 404) == 404
|
|
118
|
+
|
|
119
|
+
_, code = geoserver.delete_feature_type(workspace, datastore, renamed)
|
|
120
|
+
assert code == 200
|
|
121
|
+
|
|
122
|
+
assert wait_for_tile_layer_status(geoserver, workspace, renamed, 404) == 404
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@pytest.mark.db
|
|
126
|
+
def test_tile_layer_follows_workspace_rename(config, geoserver_factory):
|
|
127
|
+
"""Renaming a workspace must rename all its tile layers (prefixed names).
|
|
128
|
+
|
|
129
|
+
Regression test for https://github.com/geoserver/geoserver-cloud/issues/519
|
|
130
|
+
"""
|
|
131
|
+
workspace = datastore = "test_gwc_wsrename"
|
|
132
|
+
renamed_workspace = "test_gwc_wsrenamed"
|
|
133
|
+
feature_type = "ws_rename_layer"
|
|
134
|
+
geoserver: GeoServerCloud = geoserver_factory(workspace)
|
|
135
|
+
|
|
136
|
+
_, code = geoserver.create_pg_datastore(
|
|
137
|
+
workspace_name=workspace,
|
|
138
|
+
datastore_name=datastore,
|
|
139
|
+
pg_host=config["db"]["pg_host"]["docker"],
|
|
140
|
+
pg_port=config["db"]["pg_port"]["docker"],
|
|
141
|
+
pg_db=config["db"]["pg_db"],
|
|
142
|
+
pg_user=config["db"]["pg_user"],
|
|
143
|
+
pg_password=config["db"]["pg_password"],
|
|
144
|
+
pg_schema=config["db"]["pg_schema"],
|
|
145
|
+
set_default_datastore=True,
|
|
146
|
+
)
|
|
147
|
+
assert code == 201
|
|
148
|
+
|
|
149
|
+
attributes = {"geom": {"type": "Point", "required": True}}
|
|
150
|
+
_, code = geoserver.create_feature_type(
|
|
151
|
+
feature_type, attributes=attributes, epsg=4326, workspace_name=workspace
|
|
152
|
+
)
|
|
153
|
+
assert code == 201
|
|
154
|
+
assert wait_for_tile_layer_status(geoserver, workspace, feature_type, 200) == 200
|
|
155
|
+
|
|
156
|
+
response = geoserver.rest_service.rest_client.put(
|
|
157
|
+
f"/rest/workspaces/{workspace}.json",
|
|
158
|
+
json={"workspace": {"name": renamed_workspace}},
|
|
159
|
+
)
|
|
160
|
+
assert response.status_code == 200
|
|
161
|
+
|
|
162
|
+
try:
|
|
163
|
+
assert (
|
|
164
|
+
wait_for_tile_layer_status(geoserver, renamed_workspace, feature_type, 200)
|
|
165
|
+
== 200
|
|
166
|
+
)
|
|
167
|
+
assert (
|
|
168
|
+
wait_for_tile_layer_status(geoserver, workspace, feature_type, 404) == 404
|
|
169
|
+
)
|
|
170
|
+
finally:
|
|
171
|
+
# rename back to the original name for the workspace cleanup finalizer
|
|
172
|
+
geoserver.rest_service.rest_client.put(
|
|
173
|
+
f"/rest/workspaces/{renamed_workspace}.json",
|
|
174
|
+
json={"workspace": {"name": workspace}},
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
@pytest.mark.db
|
|
179
|
+
def test_tile_layer_rename_after_tile_layer_recreated_through_gwc(
|
|
180
|
+
config, geoserver_factory
|
|
181
|
+
):
|
|
182
|
+
"""Layer renames must reach every service even when the service handling the
|
|
183
|
+
rename has not touched the tile layer since another service last changed it.
|
|
184
|
+
|
|
185
|
+
The tile layer is deleted and recreated through the GWC service, then the
|
|
186
|
+
feature type is renamed through the REST API. The tile layer must follow the
|
|
187
|
+
rename regardless of which service changed it last.
|
|
188
|
+
"""
|
|
189
|
+
workspace = datastore = "test_gwc_coldrename"
|
|
190
|
+
feature_type = "cold_rename_layer"
|
|
191
|
+
renamed = "cold_rename_layer_renamed"
|
|
192
|
+
geoserver: GeoServerCloud = geoserver_factory(workspace)
|
|
193
|
+
|
|
194
|
+
_, code = geoserver.create_pg_datastore(
|
|
195
|
+
workspace_name=workspace,
|
|
196
|
+
datastore_name=datastore,
|
|
197
|
+
pg_host=config["db"]["pg_host"]["docker"],
|
|
198
|
+
pg_port=config["db"]["pg_port"]["docker"],
|
|
199
|
+
pg_db=config["db"]["pg_db"],
|
|
200
|
+
pg_user=config["db"]["pg_user"],
|
|
201
|
+
pg_password=config["db"]["pg_password"],
|
|
202
|
+
pg_schema=config["db"]["pg_schema"],
|
|
203
|
+
set_default_datastore=True,
|
|
204
|
+
)
|
|
205
|
+
assert code == 201
|
|
206
|
+
|
|
207
|
+
attributes = {"geom": {"type": "Point", "required": True}}
|
|
208
|
+
_, code = geoserver.create_feature_type(
|
|
209
|
+
feature_type, attributes=attributes, epsg=4326, workspace_name=workspace
|
|
210
|
+
)
|
|
211
|
+
assert code == 201
|
|
212
|
+
assert wait_for_tile_layer_status(geoserver, workspace, feature_type, 200) == 200
|
|
213
|
+
|
|
214
|
+
# recreate the tile layer through the GWC service
|
|
215
|
+
_, code = geoserver.delete_gwc_layer(workspace, feature_type)
|
|
216
|
+
assert code == 200
|
|
217
|
+
assert wait_for_tile_layer_status(geoserver, workspace, feature_type, 404) == 404
|
|
218
|
+
_, code = geoserver.publish_gwc_layer(workspace, feature_type)
|
|
219
|
+
assert code == 200
|
|
220
|
+
assert wait_for_tile_layer_status(geoserver, workspace, feature_type, 200) == 200
|
|
221
|
+
|
|
222
|
+
# rename the feature type through the REST API
|
|
223
|
+
response = geoserver.rest_service.rest_client.put(
|
|
224
|
+
f"/rest/workspaces/{workspace}/datastores/{datastore}/featuretypes/{feature_type}.json",
|
|
225
|
+
json={"featureType": {"name": renamed}},
|
|
226
|
+
)
|
|
227
|
+
assert response.status_code == 200
|
|
228
|
+
|
|
229
|
+
assert wait_for_tile_layer_status(geoserver, workspace, renamed, 200) == 200
|
|
230
|
+
assert wait_for_tile_layer_status(geoserver, workspace, feature_type, 404) == 404
|
|
231
|
+
|
|
232
|
+
_, code = geoserver.delete_feature_type(workspace, datastore, renamed)
|
|
233
|
+
assert code == 200
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
@pytest.mark.db
|
|
237
|
+
def test_workspace_rename_after_tile_layer_recreated_through_gwc(
|
|
238
|
+
config, geoserver_factory
|
|
239
|
+
):
|
|
240
|
+
"""Workspace renames must rename tile layers even when the service handling
|
|
241
|
+
the rename has not touched them since another service last changed them.
|
|
242
|
+
"""
|
|
243
|
+
workspace = datastore = "test_gwc_coldws"
|
|
244
|
+
renamed_workspace = "test_gwc_coldws_renamed"
|
|
245
|
+
feature_type = "cold_ws_layer"
|
|
246
|
+
geoserver: GeoServerCloud = geoserver_factory(workspace)
|
|
247
|
+
|
|
248
|
+
_, code = geoserver.create_pg_datastore(
|
|
249
|
+
workspace_name=workspace,
|
|
250
|
+
datastore_name=datastore,
|
|
251
|
+
pg_host=config["db"]["pg_host"]["docker"],
|
|
252
|
+
pg_port=config["db"]["pg_port"]["docker"],
|
|
253
|
+
pg_db=config["db"]["pg_db"],
|
|
254
|
+
pg_user=config["db"]["pg_user"],
|
|
255
|
+
pg_password=config["db"]["pg_password"],
|
|
256
|
+
pg_schema=config["db"]["pg_schema"],
|
|
257
|
+
set_default_datastore=True,
|
|
258
|
+
)
|
|
259
|
+
assert code == 201
|
|
260
|
+
|
|
261
|
+
attributes = {"geom": {"type": "Point", "required": True}}
|
|
262
|
+
_, code = geoserver.create_feature_type(
|
|
263
|
+
feature_type, attributes=attributes, epsg=4326, workspace_name=workspace
|
|
264
|
+
)
|
|
265
|
+
assert code == 201
|
|
266
|
+
assert wait_for_tile_layer_status(geoserver, workspace, feature_type, 200) == 200
|
|
267
|
+
|
|
268
|
+
# recreate the tile layer through the GWC service
|
|
269
|
+
_, code = geoserver.delete_gwc_layer(workspace, feature_type)
|
|
270
|
+
assert code == 200
|
|
271
|
+
assert wait_for_tile_layer_status(geoserver, workspace, feature_type, 404) == 404
|
|
272
|
+
_, code = geoserver.publish_gwc_layer(workspace, feature_type)
|
|
273
|
+
assert code == 200
|
|
274
|
+
assert wait_for_tile_layer_status(geoserver, workspace, feature_type, 200) == 200
|
|
275
|
+
|
|
276
|
+
# rename the workspace through the REST API
|
|
277
|
+
response = geoserver.rest_service.rest_client.put(
|
|
278
|
+
f"/rest/workspaces/{workspace}.json",
|
|
279
|
+
json={"workspace": {"name": renamed_workspace}},
|
|
280
|
+
)
|
|
281
|
+
assert response.status_code == 200
|
|
282
|
+
|
|
283
|
+
try:
|
|
284
|
+
assert (
|
|
285
|
+
wait_for_tile_layer_status(geoserver, renamed_workspace, feature_type, 200)
|
|
286
|
+
== 200
|
|
287
|
+
)
|
|
288
|
+
assert (
|
|
289
|
+
wait_for_tile_layer_status(geoserver, workspace, feature_type, 404) == 404
|
|
290
|
+
)
|
|
291
|
+
finally:
|
|
292
|
+
geoserver.rest_service.rest_client.put(
|
|
293
|
+
f"/rest/workspaces/{renamed_workspace}.json",
|
|
294
|
+
json={"workspace": {"name": workspace}},
|
|
295
|
+
)
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""Acceptance tests for the REST resource API (/rest/resource/**).
|
|
2
|
+
|
|
3
|
+
Regression coverage for https://github.com/geoserver/geoserver-cloud/issues/913:
|
|
4
|
+
requests whose path contains "/gwc" anywhere, such as /rest/resource/gwc-gs.xml,
|
|
5
|
+
used to fail with a 500 NPE ("Cannot invoke String.substring(int) because path
|
|
6
|
+
is null") or a 404 for existing resources, because the servlet filters that
|
|
7
|
+
rebuild getPathInfo() in GeoServer Cloud mistook them for GeoWebCache requests.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import pytest
|
|
11
|
+
|
|
12
|
+
from geoservercloud import GeoServerCloud
|
|
13
|
+
|
|
14
|
+
RESOURCE_API = "/rest/resource"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@pytest.fixture
|
|
18
|
+
def rest_client(geoserver: GeoServerCloud):
|
|
19
|
+
return geoserver.rest_service.rest_client
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@pytest.fixture
|
|
23
|
+
def resource_directory(rest_client, request):
|
|
24
|
+
"""Factory for a resource directory deleted (recursively) on teardown."""
|
|
25
|
+
|
|
26
|
+
def _create(directory_name):
|
|
27
|
+
request.addfinalizer(
|
|
28
|
+
lambda: rest_client.delete(f"{RESOURCE_API}/{directory_name}")
|
|
29
|
+
)
|
|
30
|
+
return directory_name
|
|
31
|
+
|
|
32
|
+
return _create
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_get_gwc_config_file(rest_client):
|
|
36
|
+
"""GET an existing file whose name contains "gwc": the exact request from issue #913."""
|
|
37
|
+
response = rest_client.get(f"{RESOURCE_API}/gwc-gs.xml")
|
|
38
|
+
assert response.status_code == 200
|
|
39
|
+
assert "<GeoServerGWCConfig>" in response.text
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_root_listing_contains_gwc_config_file(rest_client):
|
|
43
|
+
response = rest_client.get(RESOURCE_API, params={"format": "json"})
|
|
44
|
+
assert response.status_code == 200
|
|
45
|
+
assert "gwc-gs.xml" in response.text
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_nonexistent_gwc_prefixed_path_returns_404(rest_client):
|
|
49
|
+
"""Missing resources must report 404, not a 500 NPE (issue #913)."""
|
|
50
|
+
response = rest_client.get(f"{RESOURCE_API}/gwcfoo")
|
|
51
|
+
assert response.status_code == 404
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def test_roundtrip_in_gwc_named_directory(rest_client, resource_directory):
|
|
55
|
+
"""Create, list, read and delete inside a directory whose name starts with "gwc"."""
|
|
56
|
+
directory = resource_directory("gwc913dir")
|
|
57
|
+
file_path = f"{RESOURCE_API}/{directory}/child.txt"
|
|
58
|
+
|
|
59
|
+
put_text_resource(rest_client, file_path, "issue #913 directory probe")
|
|
60
|
+
|
|
61
|
+
listing = rest_client.get(f"{RESOURCE_API}/{directory}", params={"format": "json"})
|
|
62
|
+
assert listing.status_code == 200
|
|
63
|
+
assert "child.txt" in listing.text
|
|
64
|
+
|
|
65
|
+
assert_file_roundtrip(rest_client, file_path, "issue #913 directory probe")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def test_roundtrip_on_gwc_prefixed_file_name(rest_client, resource_directory):
|
|
69
|
+
"""Create, read and delete a file whose name starts with "gwc" (issue #913)."""
|
|
70
|
+
directory = resource_directory("resource_api_913")
|
|
71
|
+
file_path = f"{RESOURCE_API}/{directory}/gwc-913-probe.txt"
|
|
72
|
+
|
|
73
|
+
put_text_resource(rest_client, file_path, "issue #913 file name probe")
|
|
74
|
+
assert_file_roundtrip(rest_client, file_path, "issue #913 file name probe")
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def test_roundtrip_on_plain_file_name(rest_client, resource_directory):
|
|
78
|
+
"""Baseline coverage of the resource API on a path without "gwc" in it."""
|
|
79
|
+
directory = resource_directory("resource_api_plain")
|
|
80
|
+
file_path = f"{RESOURCE_API}/{directory}/probe.txt"
|
|
81
|
+
|
|
82
|
+
put_text_resource(rest_client, file_path, "plain resource probe")
|
|
83
|
+
|
|
84
|
+
metadata = rest_client.get(
|
|
85
|
+
file_path, params={"operation": "metadata", "format": "json"}
|
|
86
|
+
)
|
|
87
|
+
assert metadata.status_code == 200
|
|
88
|
+
assert "probe.txt" in metadata.text
|
|
89
|
+
|
|
90
|
+
assert_file_roundtrip(rest_client, file_path, "plain resource probe")
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def put_text_resource(rest_client, file_path, contents):
|
|
94
|
+
response = rest_client.put(
|
|
95
|
+
file_path, data=contents, headers={"Content-Type": "text/plain"}
|
|
96
|
+
)
|
|
97
|
+
assert response.status_code in (200, 201)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def assert_file_roundtrip(rest_client, file_path, contents):
|
|
101
|
+
"""The file must be readable, deletable, and report 404 once deleted."""
|
|
102
|
+
response = rest_client.get(file_path)
|
|
103
|
+
assert response.status_code == 200
|
|
104
|
+
assert response.text == contents
|
|
105
|
+
|
|
106
|
+
response = rest_client.delete(file_path)
|
|
107
|
+
assert response.status_code == 200
|
|
108
|
+
|
|
109
|
+
response = rest_client.get(file_path)
|
|
110
|
+
assert response.status_code == 404
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "geoservercloud"
|
|
3
|
-
version = "0.8.
|
|
3
|
+
version = "0.8.11.dev1"
|
|
4
4
|
description = "Lightweight Python client to interact with GeoServer Cloud REST API, GeoServer ACL and OGC services"
|
|
5
5
|
authors = ["Camptocamp <info@camptocamp.com>"]
|
|
6
6
|
license = "BSD-2-Clause"
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
from geoservercloud import GeoServerCloud
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def test_tile_cache(geoserver_factory):
|
|
5
|
-
workspace = "test_gwc"
|
|
6
|
-
wmts_store = "test_gwc_store"
|
|
7
|
-
wmts_layer = "ch.swisstopo.swissimage"
|
|
8
|
-
geoserver: GeoServerCloud = geoserver_factory(workspace)
|
|
9
|
-
|
|
10
|
-
content, status = geoserver.create_wmts_store(
|
|
11
|
-
workspace,
|
|
12
|
-
wmts_store,
|
|
13
|
-
capabilities="https://wmts.geo.admin.ch/EPSG/4326/1.0.0/WMTSCapabilities.xml",
|
|
14
|
-
)
|
|
15
|
-
assert status == 201
|
|
16
|
-
assert content == wmts_store
|
|
17
|
-
|
|
18
|
-
content, status = geoserver.create_wmts_layer(workspace, wmts_store, wmts_layer)
|
|
19
|
-
assert status == 201
|
|
20
|
-
assert content == wmts_layer
|
|
21
|
-
|
|
22
|
-
content, status = geoserver.publish_gwc_layer(workspace, wmts_layer)
|
|
23
|
-
assert status == 200
|
|
24
|
-
assert content in ["", "layer saved"]
|
|
25
|
-
|
|
26
|
-
response = geoserver.get_tile(
|
|
27
|
-
format="image/png",
|
|
28
|
-
layer=f"{workspace}:{wmts_layer}",
|
|
29
|
-
tile_matrix_set="EPSG:4326",
|
|
30
|
-
tile_matrix="EPSG:4326:9",
|
|
31
|
-
row=122,
|
|
32
|
-
column=534,
|
|
33
|
-
)
|
|
34
|
-
assert response.info().get("Content-Type") == "image/png"
|
|
35
|
-
assert response.info().get("Geowebcache-Cache-Result") == "MISS"
|
|
36
|
-
|
|
37
|
-
response = geoserver.get_tile(
|
|
38
|
-
format="image/png",
|
|
39
|
-
layer=f"{workspace}:{wmts_layer}",
|
|
40
|
-
tile_matrix_set="EPSG:4326",
|
|
41
|
-
tile_matrix="EPSG:4326:9",
|
|
42
|
-
row=122,
|
|
43
|
-
column=534,
|
|
44
|
-
)
|
|
45
|
-
assert response.info().get("Geowebcache-Cache-Result") == "HIT"
|
|
File without changes
|
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/.gitignore
RENAMED
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/README.md
RENAMED
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/__init__.py
RENAMED
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/ci.config.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoserver_acceptance_tests/tests/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/geoservercloudsync.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/abstractlayer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/coverages.py
RENAMED
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/coveragestore.py
RENAMED
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/datastore.py
RENAMED
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/datastores.py
RENAMED
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/featuretype.py
RENAMED
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/featuretypes.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/layergroup.py
RENAMED
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/layergroups.py
RENAMED
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/resourcedirectory.py
RENAMED
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/s3blobstore.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/wmssettings.py
RENAMED
|
File without changes
|
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/wmtsstore.py
RENAMED
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/workspace.py
RENAMED
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/models/workspaces.py
RENAMED
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/services/__init__.py
RENAMED
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/services/owsservice.py
RENAMED
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/services/restclient.py
RENAMED
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/services/restlogger.py
RENAMED
|
File without changes
|
{geoservercloud-0.8.10.dev6 → geoservercloud-0.8.11.dev1}/geoservercloud/services/restservice.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|