Follow-up to #14524. store is already null for remote datasets. workspace cannot follow the same way yet, because unlike store it is read directly (not only through is_remote_resource()-guarded GeoFence paths) in several places that assume a non-null value.
Line references below are pinned to 246ecde5 on branch 14524_remove.
What is already safe
Every GeoFence-related caller of get_dataset_workspace() is covered by the #14524 fixes:
What blocks nulling it
1. ArcGIS harvester reuses the same workspace variable for both the field value and the alternate string.
See arcgis.py lines 208-209 and 233
(the same pattern repeats at lines 312-313 and 337):
workspace = "remoteWorkspace" feeds both alternate = f"{workspace}:{name}" and "workspace": workspace in the same dict.
Nulling workspace naively turns alternate into "None:<name>".
Needs decoupling: build alternate from a literal, set additional_parameters["workspace"] = None separately.
2. set_style has no remote guard.
resource/manager.py:480
calls self._concrete_resource_manager.set_style(...) unconditionally (gated only on sld_file/sld_uploaded being present on an update call), with no is_remote_resource() check. That reaches geoserver/helpers.py's set_dataset_style() / save_style(), which call
gs_catalog.get_style(name, workspace=saved_dataset.workspace) / create_style(..., workspace=...) against the local GeoServer.
Today workspace="remoteWorkspace" there is harmless: GeoServer has no such workspace, so the lookup just misses. With workspace=None, get_style()/create_style() mean unscoped/global style, which is a real behavior change and could collide with an unrelated global style of the same name.
This gap predates #14524 and should be fixed regardless of the workspace change.
3. Persisted, user-visible link names embed the raw value.
utils.py lines 1530, 1545, 1566:
ogc_wms_name = f"OGC WMS: {instance.workspace} Service" (and the WFS/WCS
equivalents). With workspace=None these become literally "OGC WMS: None Service" on every remote dataset's page. Not a crash, but a visible regression.
4. Dataset.workspace is not nullable today.
layers/models.py:120:
workspace = models.CharField(_("Workspace"), max_length=255), no null=True.
A migration is needed, same shape as layers/migrations/0047_alter_dataset_store.py.
Tasks in scope
- Migration: make
workspace nullable.
- Harvesters (
wms.py, arcgis.py x2) and service handlers set workspace: None in their additional_parameters / indexed-dataset fields, decoupling ArcGIS's alternate construction from the field value.
- Guard
resource/manager.py's set_style dispatch with is_remote_resource().
- Fix the three OGC link-name f-strings in
utils.py to omit or fall back sensibly when workspace is falsy.
Follow-up to #14524.
storeis already null for remote datasets.workspacecannot follow the same way yet, because unlikestoreit is read directly (not only throughis_remote_resource()-guarded GeoFence paths) in several places that assume a non-null value.Line references below are pinned to
246ecde5on branch14524_remove.What is already safe
Every GeoFence-related caller of
get_dataset_workspace()is covered by the #14524 fixes:geoserver/manager.py'sremove_permissions/set_permissionsread it, but are only reached through the dispatcher inresource/manager.py, which skips remote resources.geoserver/security.py'ssync_resources_with_guardian()skips remote resources before it gets there.
delete_geofence_rules_for_layer/allow_layer_to_allhave no production callers.What blocks nulling it
1. ArcGIS harvester reuses the same
workspacevariable for both the field value and thealternatestring.See
arcgis.pylines 208-209 and 233(the same pattern repeats at lines 312-313 and 337):
workspace = "remoteWorkspace"feeds bothalternate = f"{workspace}:{name}"and"workspace": workspacein the same dict.Nulling
workspacenaively turnsalternateinto"None:<name>".Needs decoupling: build
alternatefrom a literal, setadditional_parameters["workspace"] = Noneseparately.2.
set_stylehas no remote guard.resource/manager.py:480calls
self._concrete_resource_manager.set_style(...)unconditionally (gated only onsld_file/sld_uploadedbeing present on an update call), with nois_remote_resource()check. That reachesgeoserver/helpers.py'sset_dataset_style()/save_style(), which callgs_catalog.get_style(name, workspace=saved_dataset.workspace)/create_style(..., workspace=...)against the local GeoServer.Today
workspace="remoteWorkspace"there is harmless: GeoServer has no such workspace, so the lookup just misses. Withworkspace=None,get_style()/create_style()mean unscoped/global style, which is a real behavior change and could collide with an unrelated global style of the same name.This gap predates #14524 and should be fixed regardless of the workspace change.
3. Persisted, user-visible link names embed the raw value.
utils.pylines 1530, 1545, 1566:ogc_wms_name = f"OGC WMS: {instance.workspace} Service"(and the WFS/WCSequivalents). With
workspace=Nonethese become literally"OGC WMS: None Service"on every remote dataset's page. Not a crash, but a visible regression.4.
Dataset.workspaceis not nullable today.layers/models.py:120:workspace = models.CharField(_("Workspace"), max_length=255), nonull=True.A migration is needed, same shape as
layers/migrations/0047_alter_dataset_store.py.Tasks in scope
workspacenullable.wms.py,arcgis.pyx2) and service handlers setworkspace: Nonein theiradditional_parameters/ indexed-dataset fields, decoupling ArcGIS'salternateconstruction from the field value.resource/manager.py'sset_styledispatch withis_remote_resource().utils.pyto omit or fall back sensibly whenworkspaceis falsy.