Skip to content

Commit 24bee13

Browse files
authored
Merge pull request #79 from PDOK/wr/validate-feauretypes
Wr/validate feauretypes
2 parents 0c70f55 + 3ec1fc3 commit 24bee13

28 files changed

+823
-298
lines changed

api/v2beta1/shared_conversion.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ func ConvertV2DataToV3(v2 Data) pdoknlv3.Data {
164164
if v2.Tif != nil {
165165
v3.TIF = &pdoknlv3.TIF{
166166
BlobKey: v2.Tif.BlobKey,
167-
Resample: v2.Tif.Resample,
167+
Resample: *v2.Tif.Resample,
168168
Offsite: v2.Tif.Offsite,
169169
GetFeatureInfoIncludesClass: smoothoperatorutils.PointerVal(v2.Tif.GetFeatureInfoIncludesClass, false),
170170
}
@@ -201,7 +201,7 @@ func ConvertV3DataToV2(v3 pdoknlv3.Data) Data {
201201
v2.Tif = &Tif{
202202
BlobKey: v3.TIF.BlobKey,
203203
Offsite: v3.TIF.Offsite,
204-
Resample: v3.TIF.Resample,
204+
Resample: &v3.TIF.Resample,
205205
GetFeatureInfoIncludesClass: &v3.TIF.GetFeatureInfoIncludesClass,
206206
}
207207
}

api/v2beta1/wfs_conversion.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ func convertV2FeatureTypeToV3(src FeatureType) pdoknlv3.FeatureType {
180180

181181
if src.Extent != nil {
182182
featureTypeV3.Bbox = &pdoknlv3.FeatureBbox{
183-
DefaultCRS: smoothoperatormodel.ExtentToBBox(*src.Extent),
183+
DefaultCRS: smoothoperatorutils.Pointer(smoothoperatormodel.ExtentToBBox(*src.Extent)),
184184
}
185185
}
186186

api/v3/shared_types.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,6 @@ type Data struct {
171171
type Gpkg struct {
172172
// Blobkey identifies the location/bucket of the .gpkg file
173173
// +kubebuilder:validation:Pattern:=^.+\/.+\/.+\.gpkg$
174-
// +kubebuilder:validation:MinLength:=1
175174
BlobKey string `json:"blobKey"`
176175

177176
// TableName is the table within the geopackage
@@ -180,7 +179,6 @@ type Gpkg struct {
180179

181180
// GeometryType of the table, must match an OGC type
182181
// +kubebuilder:validation:Pattern:=`^(Multi)?(Point|LineString|Polygon)$`
183-
// +kubebuilder:validation:MinLength:=1
184182
GeometryType string `json:"geometryType"`
185183

186184
// Columns to visualize for this table
@@ -209,18 +207,15 @@ type Postgis struct {
209207
// +kubebuilder:validation:Type=object
210208
type TIF struct {
211209
// BlobKey to the TIFF file
212-
// +kubebuilder:validation:Pattern=`\.(tif?f|vrt)$`
213-
// +kubebuilder:validation:MinLength:=1
210+
// +kubebuilder:validation:Pattern:=`^.+\/.+\/.+\.(tif?f|vrt)$`
214211
BlobKey string `json:"blobKey"`
215212

216213
// This option can be used to control the resampling kernel used sampling raster images, optional
217-
// +kubebuilder:validation:MinLength:=1
218214
// +kubebuilder:validation:Pattern=`(NEAREST|AVERAGE|BILINEAR)`
219215
// +kubebuilder:default=NEAREST
220-
Resample *string `json:"resample,omitempty"`
216+
Resample string `json:"resample,omitempty"`
221217

222218
// Sets the color index to treat as transparent for raster layers, optional, hex or rgb
223-
// +kubebuilder:validation:MinLength:=1
224219
// +kubebuilder:validation:Pattern=`(#[0-9A-F]{6}([0-9A-F]{2})?)|([0-9]{1,3}\s[0-9]{1,3}\s[0-9]{1,3})`
225220
Offsite *string `json:"offsite,omitempty"`
226221

api/v3/shared_validation.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,4 +128,12 @@ func ValidateInspire[O WMSWFS](obj O, allErrs *field.ErrorList) {
128128
}
129129
}
130130

131+
if obj.Type() == ServiceTypeWFS && len(datasetIDs) > 1 {
132+
*allErrs = append(*allErrs, field.Invalid(
133+
field.NewPath("spec").Child("service").Child("featureTypes[*]").Child("datasetMetadataUrl").Child("csw").Child("metadataIdentifier"),
134+
datasetIDs,
135+
"when Inspire, all featureTypes need use the same datasetMetadataUrl.csw.metadataIdentifier",
136+
))
137+
}
138+
131139
}

api/v3/wfs_types.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@ type WFSService struct {
137137

138138
// Default CRS (DataEPSG)
139139
// +kubebuilder:validation:Pattern:="^EPSG:(28992|25831|25832|3034|3035|3857|4258|4326)$"
140-
// +kubebuilder:validation:MinLength:=1
141140
DefaultCrs string `json:"defaultCrs"`
142141

143142
// Other supported CRS
@@ -169,7 +168,6 @@ func (s WFSService) KeywordsIncludingInspireKeyword() []string {
169168

170169
// HealthCheck is the struct with all fields to configure custom healthchecks
171170
type HealthCheckWFS struct {
172-
// +kubebuilder:validation:MinLength:=1
173171
// +kubebuilder:validation:XValidation:rule="self.contains('Service=WFS')",message="a valid healthcheck contains 'Service=WFS'"
174172
// +kubebuilder:validation:XValidation:rule="self.contains('Request=')",message="a valid healthcheck contains 'Request='"
175173
Querystring string `json:"querystring"`
@@ -187,7 +185,7 @@ type Bbox struct {
187185
// FeatureType defines a WFS feature
188186
type FeatureType struct {
189187
// Name of the feature
190-
// +kubebuilder:validation:MinLength:=1
188+
// +kubebuilder:validation:Pattern:=`^\S+$`
191189
Name string `json:"name"`
192190

193191
// Title of the feature
@@ -217,14 +215,14 @@ type FeatureType struct {
217215
Data Data `json:"data"`
218216
}
219217

220-
// FeatureType bounding box, if provided it overrides the default extent
218+
// FeatureBbox is the optional featureType bounding box, if provided it overrides the default extent
221219
type FeatureBbox struct {
222-
// DefaultCRS defines the feature’s bounding box in the service’s own CRS
220+
// DefaultCRS defines the EXTENT/wfs_extent for the featureType for use in the mapfile
223221
//nolint:tagliatelle
224222
// +kubebuilder:validation:Type=object
225-
DefaultCRS smoothoperatormodel.BBox `json:"defaultCRS"`
223+
DefaultCRS *smoothoperatormodel.BBox `json:"defaultCRS,omitempty"`
226224

227-
// WGS84, if provided, gives the same bounding box reprojected into EPSG:4326.
225+
// WGS84, if provided, gives the same bounding box reprojected into EPSG:4326 for use in the capabilities.
228226
// +kubebuilder:validation:Type=object
229227
WGS84 *smoothoperatormodel.BBox `json:"wgs84,omitempty"`
230228
}

api/v3/wfs_validation.go

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

33
import (
4+
"slices"
45
"strings"
56

67
sharedValidation "github.com/pdok/smooth-operator/pkg/validation"
@@ -69,4 +70,64 @@ func ValidateWFS(wfs *WFS, warnings *[]string, allErrs *field.ErrorList) {
6970

7071
podSpecPatch := wfs.Spec.PodSpecPatch
7172
ValidateEphemeralStorage(podSpecPatch, allErrs)
73+
74+
ValidateFeatureTypes(wfs, warnings, allErrs)
75+
}
76+
77+
func ValidateFeatureTypes(wfs *WFS, warnings *[]string, allErrs *field.ErrorList) {
78+
names := []string{}
79+
path := field.NewPath("spec").Child("service").Child("featureTypes")
80+
for index, featureType := range wfs.Spec.Service.FeatureTypes {
81+
if slices.Contains(names, featureType.Name) {
82+
*allErrs = append(*allErrs, field.Duplicate(
83+
path.Index(index).Child("name"),
84+
featureType.Name,
85+
))
86+
} else {
87+
names = append(names, featureType.Name)
88+
}
89+
90+
if wfs.Spec.Service.Mapfile != nil && featureType.Bbox != nil && featureType.Bbox.DefaultCRS != nil {
91+
sharedValidation.AddWarning(
92+
warnings,
93+
*path.Index(index).Child("bbox").Child("defaultCrs"),
94+
"is not used when service.mapfile is configured",
95+
wfs.GroupVersionKind(),
96+
wfs.GetName(),
97+
)
98+
}
99+
100+
if tif := featureType.Data.TIF; tif != nil {
101+
if tif.Resample != "NEAREST" {
102+
sharedValidation.AddWarning(
103+
warnings,
104+
*path.Index(index).Child("data").Child("tif").Child("resample"),
105+
"is not used when service.mapfile is configured",
106+
wfs.GroupVersionKind(),
107+
wfs.GetName(),
108+
)
109+
}
110+
111+
if tif.Offsite != nil {
112+
sharedValidation.AddWarning(
113+
warnings,
114+
*path.Index(index).Child("data").Child("tif").Child("offsite"),
115+
"is not used when service.mapfile is configured",
116+
wfs.GroupVersionKind(),
117+
wfs.GetName(),
118+
)
119+
}
120+
121+
if tif.GetFeatureInfoIncludesClass {
122+
sharedValidation.AddWarning(
123+
warnings,
124+
*path.Index(index).Child("data").Child("tif").Child("getFeatureInfoIncludesClass"),
125+
"is not used when service.mapfile is configured",
126+
wfs.GroupVersionKind(),
127+
wfs.GetName(),
128+
)
129+
}
130+
}
131+
132+
}
72133
}

api/v3/zz_generated.deepcopy.go

Lines changed: 5 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ const (
5757
defaultMultitoolImage = "acrpdokprodman.azurecr.io/pdok/docker-multitool:0.9.4"
5858
defaultMapfileGeneratorImage = "acrpdokprodman.azurecr.io/pdok/mapfile-generator:1.9.5"
5959
defaultMapserverImage = "acrpdokprodman.azurecr.io/mirror/docker.io/pdok/mapserver:8.4.0-4-nl"
60-
defaultCapabilitiesGeneratorImage = "acrpdokprodman.azurecr.io/mirror/docker.io/pdok/ogc-capabilities-generator:1.0.0-beta8"
60+
defaultCapabilitiesGeneratorImage = "acrpdokprodman.azurecr.io/mirror/docker.io/pdok/ogc-capabilities-generator:1.0.0-beta9"
6161
defaultFeatureinfoGeneratorImage = "acrpdokprodman.azurecr.io/mirror/docker.io/pdok/featureinfo-generator:1.4.0-beta1"
6262
defaultOgcWebserviceProxyImage = "acrpdokprodman.azurecr.io/pdok/ogc-webservice-proxy:0.1.8"
6363
defaultApacheExporterImage = "acrpdokprodman.azurecr.io/mirror/docker.io/lusotycoon/apache-exporter:v0.7.0"

0 commit comments

Comments
 (0)