diff --git a/api/v3/wms_types.go b/api/v3/wms_types.go index 8d0aeff..d24c6cf 100644 --- a/api/v3/wms_types.go +++ b/api/v3/wms_types.go @@ -240,7 +240,7 @@ type Layer struct { // +kubebuilder:validation:Pattern:=`^[0-9]+(.[0-9]+)?$` MinScaleDenominator *string `json:"minscaledenominator,omitempty"` - // The maximum scale at which this layer functions, defaults to 15000000 + // The maximum scale at which this layer functions, inherited from its parent when omitted (top-layer default: 15000000) // +kubebuilder:default:="15000000" // +kubebuilder:validation:Pattern:=`^[1-9][0-9]*(.[0-9]+)?$` MaxScaleDenominator *string `json:"maxscaledenominator,omitempty"` diff --git a/config/crd/bases/pdok.nl_wfs.yaml b/config/crd/bases/pdok.nl_wfs.yaml index ddc6127..d8251b9 100644 --- a/config/crd/bases/pdok.nl_wfs.yaml +++ b/config/crd/bases/pdok.nl_wfs.yaml @@ -144,8 +144,8 @@ spec: and scale-down and scale-up tolerances of 5% and 1% respectively, scaling will be triggered when the actual consumption falls below 95Mi or exceeds 101Mi. - This is an alpha field and requires enabling the HPAConfigurableTolerance - feature gate. + This is an beta field and requires the HPAConfigurableTolerance feature + gate to be enabled. pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true type: object @@ -217,8 +217,8 @@ spec: and scale-down and scale-up tolerances of 5% and 1% respectively, scaling will be triggered when the actual consumption falls below 95Mi or exceeds 101Mi. - This is an alpha field and requires enabling the HPAConfigurableTolerance - feature gate. + This is an beta field and requires the HPAConfigurableTolerance feature + gate to be enabled. pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true type: object diff --git a/config/crd/bases/pdok.nl_wms.yaml b/config/crd/bases/pdok.nl_wms.yaml index 12d5606..6cb3c38 100644 --- a/config/crd/bases/pdok.nl_wms.yaml +++ b/config/crd/bases/pdok.nl_wms.yaml @@ -171,8 +171,8 @@ spec: and scale-down and scale-up tolerances of 5% and 1% respectively, scaling will be triggered when the actual consumption falls below 95Mi or exceeds 101Mi. - This is an alpha field and requires enabling the HPAConfigurableTolerance - feature gate. + This is an beta field and requires the HPAConfigurableTolerance feature + gate to be enabled. pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true type: object @@ -244,8 +244,8 @@ spec: and scale-down and scale-up tolerances of 5% and 1% respectively, scaling will be triggered when the actual consumption falls below 95Mi or exceeds 101Mi. - This is an alpha field and requires enabling the HPAConfigurableTolerance - feature gate. + This is an beta field and requires the HPAConfigurableTolerance feature + gate to be enabled. pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true type: object @@ -1361,8 +1361,7 @@ spec: description: Mapfile setting, sets "LABEL_NO_CLIP=ON" type: boolean maxscaledenominator: - default: "15000000" - description: The maximum scale at which this layer functions, defaults to 15000000 + description: 'The maximum scale at which this layer functions, inherited from its parent when omitted (top-layer default: 15000000)' pattern: ^[1-9][0-9]*(.[0-9]+)?$ type: string minscaledenominator: @@ -1439,8 +1438,7 @@ spec: minItems: 1 type: array maxscaledenominator: - default: "15000000" - description: The maximum scale at which this layer functions, defaults to 15000000 + description: 'The maximum scale at which this layer functions, inherited from its parent when omitted (top-layer default: 15000000)' pattern: ^[1-9][0-9]*(.[0-9]+)?$ type: string minscaledenominator: @@ -1520,7 +1518,7 @@ spec: type: array maxscaledenominator: default: "15000000" - description: The maximum scale at which this layer functions, defaults to 15000000 + description: 'The maximum scale at which this layer functions, inherited from its parent when omitted (top-layer default: 15000000)' pattern: ^[1-9][0-9]*(.[0-9]+)?$ type: string minscaledenominator: diff --git a/config/crd/update_openapi.go b/config/crd/update_openapi.go index 604eb9e..7df3cb3 100644 --- a/config/crd/update_openapi.go +++ b/config/crd/update_openapi.go @@ -73,8 +73,13 @@ func updateLayersV3(version *v1.CustomResourceDefinitionVersion) { service := spec.Properties["service"] layer := service.Properties["layer"] + inheritedLayer := layer.DeepCopy() + maxScale := inheritedLayer.Properties["maxscaledenominator"] + maxScale.Default = nil + inheritedLayer.Properties["maxscaledenominator"] = maxScale + // Level 3 - layerSpecLevel3 := layer.DeepCopy() + layerSpecLevel3 := inheritedLayer.DeepCopy() layerSpecLevel3.Required = append(layerSpecLevel3.Required, "name") layerSpecLevel3.Required = append(layerSpecLevel3.Required, "styles") delete(layerSpecLevel3.Properties, "layers") @@ -87,7 +92,7 @@ func updateLayersV3(version *v1.CustomResourceDefinitionVersion) { layerSpecLevel3.XValidations = xvals // Level 2 - layerSpecLevel2 := layer.DeepCopy() + layerSpecLevel2 := inheritedLayer.DeepCopy() layerSpecLevel2.Required = append(layerSpecLevel2.Required, "name") layerSpecLevel2.Required = append(layerSpecLevel2.Required, "styles") bottomLayers := layerSpecLevel2.Properties["layers"] diff --git a/internal/controller/mapfilegenerator/mapfile_generator_test.go b/internal/controller/mapfilegenerator/mapfile_generator_test.go index 3d6726e..6dd35f3 100644 --- a/internal/controller/mapfilegenerator/mapfile_generator_test.go +++ b/internal/controller/mapfilegenerator/mapfile_generator_test.go @@ -55,6 +55,65 @@ func TestGetConfigForWMSWithGroupLayersAndTopGroupLayer(t *testing.T) { testWMS(t, "wms_group_and_toplayer") } +func TestWMSLayerScaleInheritance(t *testing.T) { + for _, testcase := range []struct { + name string + topMax *string + groupMax *string + childMax *string + groupMin *string + childMin *string + expectedMax *string + expectedMin *string + }{ + { + name: "inherit group scales", topMax: smoothoperatorutils.Pointer("15000000"), + groupMax: smoothoperatorutils.Pointer("50000"), groupMin: smoothoperatorutils.Pointer("2"), + expectedMax: smoothoperatorutils.Pointer("50000"), expectedMin: smoothoperatorutils.Pointer("2"), + }, + { + name: "inherit top scales through group", topMax: smoothoperatorutils.Pointer("15000000"), + expectedMax: smoothoperatorutils.Pointer("15000000"), expectedMin: smoothoperatorutils.Pointer("1"), + }, + { + name: "preserve child overrides", topMax: smoothoperatorutils.Pointer("15000000"), + groupMax: smoothoperatorutils.Pointer("50000"), groupMin: smoothoperatorutils.Pointer("2"), + childMax: smoothoperatorutils.Pointer("10000"), childMin: smoothoperatorutils.Pointer("3"), + expectedMax: smoothoperatorutils.Pointer("10000"), expectedMin: smoothoperatorutils.Pointer("3"), + }, + { + name: "inherit scales independently", topMax: smoothoperatorutils.Pointer("15000000"), + groupMin: smoothoperatorutils.Pointer("2"), childMax: smoothoperatorutils.Pointer("10000"), + expectedMax: smoothoperatorutils.Pointer("10000"), expectedMin: smoothoperatorutils.Pointer("2"), + }, + { + name: "leave maximum unset without ancestors", expectedMin: smoothoperatorutils.Pointer("1"), + }, + } { + t.Run(testcase.name, func(t *testing.T) { + child := pdoknlv3.Layer{ + Name: smoothoperatorutils.Pointer("child"), + MaxScaleDenominator: testcase.childMax, MinScaleDenominator: testcase.childMin, + } + var wms pdoknlv3.WMS + wms.Spec.Service.Layer = pdoknlv3.Layer{ + Name: smoothoperatorutils.Pointer("top"), + MaxScaleDenominator: testcase.topMax, MinScaleDenominator: smoothoperatorutils.Pointer("1"), + Layers: []pdoknlv3.Layer{{ + Name: smoothoperatorutils.Pointer("group"), + MaxScaleDenominator: testcase.groupMax, MinScaleDenominator: testcase.groupMin, + Layers: []pdoknlv3.Layer{child}, + }}, + } + original := wms.DeepCopy() + result := getWMSLayer(child, "", &wms) + assert.Equal(t, testcase.expectedMax, result.MaxScale) + assert.Equal(t, testcase.expectedMin, result.MinScale) + assert.Equal(t, original, &wms) + }) + } +} + func TestGetConfigForTifWMS(t *testing.T) { testWMS(t, "wms_tif") } diff --git a/internal/controller/mapfilegenerator/mapper.go b/internal/controller/mapfilegenerator/mapper.go index d2df9da..37ae6be 100644 --- a/internal/controller/mapfilegenerator/mapper.go +++ b/internal/controller/mapfilegenerator/mapper.go @@ -253,6 +253,7 @@ func mapLayers(wms *pdoknlv3.WMS, extent string, result *WMSInput) { result.EPSGList = epsgs } +//nolint:cyclop func getWMSLayer(serviceLayer pdoknlv3.Layer, serviceExtent string, wms *pdoknlv3.WMS) WMSLayer { groupName := "" parent := wms.Spec.Service.GetParentLayer(serviceLayer) @@ -301,12 +302,12 @@ func getWMSLayer(serviceLayer pdoknlv3.Layer, serviceExtent string, wms *pdoknlv } // Let child Layers inherit Scale denominators from their parent if not explicitly set. - if parent != nil { + for ancestor := parent; ancestor != nil && (result.MinScale == nil || result.MaxScale == nil); ancestor = wms.Spec.Service.GetParentLayer(*ancestor) { if result.MinScale == nil { - result.MinScale = parent.MinScaleDenominator + result.MinScale = ancestor.MinScaleDenominator } if result.MaxScale == nil { - result.MaxScale = parent.MaxScaleDenominator + result.MaxScale = ancestor.MaxScaleDenominator } } diff --git a/internal/controller/test_data/wms/custom-mapfile/expected/configmap-capabilities-generator.yaml b/internal/controller/test_data/wms/custom-mapfile/expected/configmap-capabilities-generator.yaml index 76d640e..281631a 100644 --- a/internal/controller/test_data/wms/custom-mapfile/expected/configmap-capabilities-generator.yaml +++ b/internal/controller/test_data/wms/custom-mapfile/expected/configmap-capabilities-generator.yaml @@ -139,7 +139,7 @@ metadata: pdok.nl/inspire: "false" service-type: wms service-version: v1_0 - name: custom-mapfile-wms-capabilities-generator-2hdkd2c88f + name: custom-mapfile-wms-capabilities-generator-c28fg7ffhb namespace: default ownerReferences: - apiVersion: pdok.nl/v3 diff --git a/internal/controller/test_data/wms/custom-mapfile/expected/deployment.yaml b/internal/controller/test_data/wms/custom-mapfile/expected/deployment.yaml index c54a87c..7f5e84e 100644 --- a/internal/controller/test_data/wms/custom-mapfile/expected/deployment.yaml +++ b/internal/controller/test_data/wms/custom-mapfile/expected/deployment.yaml @@ -332,7 +332,7 @@ spec: name: custom-mapfile-wms-init-scripts-f8k8ffgmgh name: init-scripts - configMap: - name: custom-mapfile-wms-capabilities-generator-2hdkd2c88f + name: custom-mapfile-wms-capabilities-generator-c28fg7ffhb defaultMode: 420 name: capabilities-generator-config - projected: diff --git a/internal/controller/test_data/wms/minimal/expected/configmap-capabilities-generator.yaml b/internal/controller/test_data/wms/minimal/expected/configmap-capabilities-generator.yaml index 9b3fab9..a784448 100644 --- a/internal/controller/test_data/wms/minimal/expected/configmap-capabilities-generator.yaml +++ b/internal/controller/test_data/wms/minimal/expected/configmap-capabilities-generator.yaml @@ -139,7 +139,7 @@ metadata: pdok.nl/inspire: "false" service-type: wms service-version: v1_0 - name: minimal-wms-capabilities-generator-2hdkd2c88f + name: minimal-wms-capabilities-generator-c28fg7ffhb namespace: default ownerReferences: - apiVersion: pdok.nl/v3 diff --git a/internal/controller/test_data/wms/minimal/expected/deployment.yaml b/internal/controller/test_data/wms/minimal/expected/deployment.yaml index c1288a1..d92baf9 100644 --- a/internal/controller/test_data/wms/minimal/expected/deployment.yaml +++ b/internal/controller/test_data/wms/minimal/expected/deployment.yaml @@ -346,7 +346,7 @@ spec: name: minimal-wms-init-scripts-f8k8ffgmgh name: init-scripts - configMap: - name: minimal-wms-capabilities-generator-2hdkd2c88f + name: minimal-wms-capabilities-generator-c28fg7ffhb defaultMode: 420 name: capabilities-generator-config - configMap: diff --git a/internal/controller/test_data/wms/noprefetch/expected/configmap-capabilities-generator.yaml b/internal/controller/test_data/wms/noprefetch/expected/configmap-capabilities-generator.yaml index 99a5d71..811ff77 100644 --- a/internal/controller/test_data/wms/noprefetch/expected/configmap-capabilities-generator.yaml +++ b/internal/controller/test_data/wms/noprefetch/expected/configmap-capabilities-generator.yaml @@ -139,7 +139,7 @@ metadata: pdok.nl/inspire: "false" service-type: wms service-version: v1_0 - name: noprefetch-wms-capabilities-generator-2hdkd2c88f + name: noprefetch-wms-capabilities-generator-c28fg7ffhb namespace: default ownerReferences: - apiVersion: pdok.nl/v3 diff --git a/internal/controller/test_data/wms/noprefetch/expected/deployment.yaml b/internal/controller/test_data/wms/noprefetch/expected/deployment.yaml index d5c0484..d5532bb 100644 --- a/internal/controller/test_data/wms/noprefetch/expected/deployment.yaml +++ b/internal/controller/test_data/wms/noprefetch/expected/deployment.yaml @@ -338,7 +338,7 @@ spec: defaultMode: 420 name: ogc-webservice-proxy-config - configMap: - name: noprefetch-wms-capabilities-generator-2hdkd2c88f + name: noprefetch-wms-capabilities-generator-c28fg7ffhb defaultMode: 420 name: capabilities-generator-config - configMap: diff --git a/internal/controller/test_data/wms/patches/expected/configmap-capabilities-generator.yaml b/internal/controller/test_data/wms/patches/expected/configmap-capabilities-generator.yaml index 9c2e387..ec1fa5a 100644 --- a/internal/controller/test_data/wms/patches/expected/configmap-capabilities-generator.yaml +++ b/internal/controller/test_data/wms/patches/expected/configmap-capabilities-generator.yaml @@ -139,7 +139,7 @@ metadata: pdok.nl/inspire: "false" service-type: wms service-version: v1_0 - name: patches-wms-capabilities-generator-tbthbk4dk2 + name: patches-wms-capabilities-generator-9t8c496b27 namespace: default ownerReferences: - apiVersion: pdok.nl/v3 diff --git a/internal/controller/test_data/wms/patches/expected/deployment.yaml b/internal/controller/test_data/wms/patches/expected/deployment.yaml index 7b2e6b9..ba31a07 100644 --- a/internal/controller/test_data/wms/patches/expected/deployment.yaml +++ b/internal/controller/test_data/wms/patches/expected/deployment.yaml @@ -354,7 +354,7 @@ spec: name: patches-wms-init-scripts-f8k8ffgmgh name: init-scripts - configMap: - name: patches-wms-capabilities-generator-tbthbk4dk2 + name: patches-wms-capabilities-generator-9t8c496b27 defaultMode: 420 name: capabilities-generator-config - configMap: