Skip to content

Commit a4781c8

Browse files
committed
wfs service validation finished
1 parent 458f4de commit a4781c8

31 files changed

+1685
-1644
lines changed

api/v2beta1/wfs_conversion.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,13 @@ func (src *WFS) ToV3(dst *pdoknlv3.WFS) error {
102102
AccessConstraints: smoothoperatormodel.URL{URL: accessConstraints},
103103
DefaultCrs: src.Spec.Service.DataEPSG,
104104
OtherCrs: []string{
105-
"EPSG::25831",
106-
"EPSG::25832",
107-
"EPSG::3034",
108-
"EPSG::3035",
109-
"EPSG::3857",
110-
"EPSG::4258",
111-
"EPSG::4326",
105+
"EPSG:25831",
106+
"EPSG:25832",
107+
"EPSG:3034",
108+
"EPSG:3035",
109+
"EPSG:3857",
110+
"EPSG:4258",
111+
"EPSG:4326",
112112
},
113113
FeatureTypes: make([]pdoknlv3.FeatureType, 0),
114114
}

api/v3/shared_types.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,12 @@ type WMSWFS interface {
4646
Options() Options
4747
HasPostgisData() bool
4848

49-
// URLPath returns the configured service URL
49+
// URL returns the configured service URL
5050
URL() smoothoperatormodel.URL
5151

52+
// DatasetMetadataIds returns list of all configured metadata identifiers configured on Layers or Featuretypes
53+
DatasetMetadataIDs() []string
54+
5255
GeoPackages() []*Gpkg
5356

5457
ReadinessQueryString() (string, string, error)
@@ -114,18 +117,18 @@ type Inspire struct {
114117
ServiceMetadataURL MetadataURL `json:"serviceMetadataUrl"`
115118

116119
// SpatialDatasetIdentifier is the ID uniquely identifying the dataset.
117-
// +kubebuilder:validation:MinLength:=1
120+
// +kubebuilder:validation:Pattern:=`^[0-9a-zA-Z]{8}\-[0-9a-zA-Z]{4}\-[0-9a-zA-Z]{4}\-[0-9a-zA-Z]{4}\-[0-9a-zA-Z]{12}$`
118121
SpatialDatasetIdentifier string `json:"spatialDatasetIdentifier"`
119122

120123
// Language of the INSPIRE metadata record
121-
// +kubebuilder:validation:MinLength:=1
124+
// +kubebuilder:validation:Pattern:=`bul|cze|dan|dut|eng|est|fin|fre|ger|gre|hun|gle|ita|lav|lit|mlt|pol|por|rum|slo|slv|spa|swe`
122125
Language string `json:"language"`
123126
}
124127

125-
// +kubebuilder:validation:XValidation:rule="(has(self.csw) || has(self.custom)) && !(has(self.csw) && has(self.custom))", message="metadataUrl should have csw or custom, not both"
128+
// +kubebuilder:validation:XValidation:rule="(has(self.csw) || has(self.custom)) && !(has(self.csw) && has(self.custom))", message="metadataUrl should have exactly 1 of csw or custom"
126129
type MetadataURL struct {
127130
// CSW describes a metadata record via a metadataIdentifier (UUID) as defined in the OwnerInfo.
128-
CSW *Metadata `json:"csw"`
131+
CSW *Metadata `json:"csw,omitempty"`
129132

130133
// Custom allows arbitrary href
131134
Custom *Custom `json:"custom,omitempty"`
@@ -134,16 +137,15 @@ type MetadataURL struct {
134137
// Metadata holds the UUID of a CSW metadata record
135138
type Metadata struct {
136139
// MetadataIdentifier is the record's UUID
137-
// +kubebuilder:validation:MinLength:=1
140+
// +kubebuilder:validation:Pattern:=`^[0-9a-zA-Z]{8}\-[0-9a-zA-Z]{4}\-[0-9a-zA-Z]{4}\-[0-9a-zA-Z]{4}\-[0-9a-zA-Z]{12}$`
138141
MetadataIdentifier string `json:"metadataIdentifier"`
139142
}
140143

141144
// Custom represents a non-CSW metadata link with a href and MIME type.
142145
// +kubebuilder:validation:Type=object
143146
type Custom struct {
144-
// +kubebuilder:validation:Pattern=`^https?://.*$`
145-
// +kubebuilder:validation:MinLength=1
146-
Href string `json:"href"`
147+
// Href of the custom metadata url
148+
Href smoothoperatormodel.URL `json:"href"`
147149

148150
// MIME type of the custom link
149151
// +kubebuilder:validation:MinLength=1

api/v3/shared_validation.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package v3
22

33
import (
44
"fmt"
5+
"slices"
56

67
sharedValidation "github.com/pdok/smooth-operator/pkg/validation"
78
v1 "k8s.io/api/core/v1"
@@ -75,3 +76,39 @@ func ValidateEphemeralStorage(podSpecPatch v1.PodSpec, allErrs *field.ErrorList)
7576
*allErrs = append(*allErrs, field.Required(path, ""))
7677
}
7778
}
79+
80+
func ValidateInspire[O WMSWFS](obj O, allErrs *field.ErrorList) {
81+
if obj.Inspire() == nil {
82+
return
83+
}
84+
85+
datasetIDs := obj.DatasetMetadataIDs()
86+
spatialID := obj.Inspire().SpatialDatasetIdentifier
87+
88+
if slices.Contains(datasetIDs, spatialID) {
89+
*allErrs = append(*allErrs, field.Invalid(
90+
field.NewPath("spec").Child("service").Child("inspire").Child("spatialDatasetIdentifier"),
91+
spatialID,
92+
"spatialDatasetIdentifier cannot also be used as an datasetMetadataUrl.csw.metadataIdentifier",
93+
))
94+
}
95+
96+
if serviceID := obj.Inspire().ServiceMetadataURL.CSW; serviceID != nil {
97+
if slices.Contains(datasetIDs, serviceID.MetadataIdentifier) {
98+
*allErrs = append(*allErrs, field.Invalid(
99+
field.NewPath("spec").Child("service").Child("inspire").Child("csw").Child("metadataIdentifier"),
100+
serviceID.MetadataIdentifier,
101+
"serviceMetadataUrl.csw.metadataIdentifier cannot also be used as an datasetMetadataUrl.csw.metadataIdentifier",
102+
))
103+
}
104+
105+
if spatialID == serviceID.MetadataIdentifier {
106+
*allErrs = append(*allErrs, field.Invalid(
107+
field.NewPath("spec").Child("service").Child("inspire").Child("csw").Child("metadataIdentifier"),
108+
serviceID.MetadataIdentifier,
109+
"serviceMetadataUrl.csw.metadataIdentifier cannot also be used as the spatialDatasetIdentifier",
110+
))
111+
}
112+
}
113+
114+
}

api/v3/wfs_types.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ type WFSSpec struct {
9090
Service WFSService `json:"service"`
9191
}
9292

93+
// +kubebuilder:validation:XValidation:message="otherCrs can't contain the defaultCrs",rule="!has(self.otherCrs) || (has(self.otherCrs) && !(self.defaultCrs in self.otherCrs))",fieldPath=".otherCrs"
9394
type WFSService struct {
9495
// Geonovum subdomein
9596
// +kubebuilder:validation:MinLength:=1
@@ -136,6 +137,7 @@ type WFSService struct {
136137

137138
// Other supported CRS
138139
// +kubebuilder:validation:MinItems:=1
140+
// +kubebuilder:validation:items:Pattern:="^EPSG:(28992|25831|25832|3034|3035|3857|4258|4326)$"
139141
OtherCrs []string `json:"otherCrs,omitempty"`
140142

141143
// Service bounding box
@@ -278,6 +280,20 @@ func (wfs *WFS) URL() smoothoperatormodel.URL {
278280
return wfs.Spec.Service.URL
279281
}
280282

283+
func (wfs *WFS) DatasetMetadataIDs() []string {
284+
ids := []string{}
285+
286+
for _, featureType := range wfs.Spec.Service.FeatureTypes {
287+
if featureType.DatasetMetadataURL != nil && featureType.DatasetMetadataURL.CSW != nil {
288+
if id := featureType.DatasetMetadataURL.CSW.MetadataIdentifier; !slices.Contains(ids, id) {
289+
ids = append(ids, id)
290+
}
291+
}
292+
}
293+
294+
return ids
295+
}
296+
281297
func (wfs *WFS) GeoPackages() []*Gpkg {
282298
gpkgs := make([]*Gpkg, 0)
283299

api/v3/wfs_validation.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ func ValidateWFS(wfs *WFS, warnings *[]string, allErrs *field.ErrorList) {
5656
sharedValidation.AddWarning(warnings, *path.Child("bbox"), "is not used when service.mapfile is configured", wfs.GroupVersionKind(), wfs.GetName())
5757
}
5858

59+
ValidateInspire(wfs, allErrs)
60+
5961
if wfs.Spec.HorizontalPodAutoscalerPatch != nil {
6062
ValidateHorizontalPodAutoscalerPatch(*wfs.Spec.HorizontalPodAutoscalerPatch, allErrs)
6163
}

api/v3/wms_types.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,20 @@ func (wms *WMS) URL() smoothoperatormodel.URL {
624624
return wms.Spec.Service.URL
625625
}
626626

627+
func (wms *WMS) DatasetMetadataIDs() []string {
628+
ids := []string{}
629+
630+
for _, layer := range wms.Spec.Service.GetAllLayers() {
631+
if layer.DatasetMetadataURL != nil && layer.DatasetMetadataURL.CSW != nil {
632+
if id := layer.DatasetMetadataURL.CSW.MetadataIdentifier; !slices.Contains(ids, id) {
633+
ids = append(ids, id)
634+
}
635+
}
636+
}
637+
638+
return ids
639+
}
640+
627641
func (wms *WMS) GeoPackages() []*Gpkg {
628642
gpkgs := make([]*Gpkg, 0)
629643

api/v3/wms_validation.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,8 @@ func ValidateWMS(wms *WMS, warnings *[]string, allErrs *field.ErrorList) {
291291
))
292292
}
293293

294+
ValidateInspire(wms, allErrs)
295+
294296
if wms.Spec.HorizontalPodAutoscalerPatch != nil {
295297
ValidateHorizontalPodAutoscalerPatch(*wms.Spec.HorizontalPodAutoscalerPatch, allErrs)
296298
}

api/v3/zz_generated.deepcopy.go

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)