diff --git a/Dockerfile b/Dockerfile index f4767ed..051474c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,6 +3,8 @@ FROM docker.io/golang:1.24 AS builder ARG TARGETOS ARG TARGETARCH +#COPY --from=repos ./smooth-operator /smooth-operator + WORKDIR /workspace # Copy the Go Modules manifests COPY go.mod go.mod diff --git a/api/v2beta1/wms_conversion.go b/api/v2beta1/wms_conversion.go index bb1fb0a..1b6634d 100644 --- a/api/v2beta1/wms_conversion.go +++ b/api/v2beta1/wms_conversion.go @@ -26,16 +26,16 @@ package v2beta1 import ( "errors" - sharedModel "github.com/pdok/smooth-operator/model" "log" "sigs.k8s.io/controller-runtime/pkg/conversion" "strconv" "strings" pdoknlv3 "github.com/pdok/mapserver-operator/api/v3" + sharedModel "github.com/pdok/smooth-operator/model" ) -const SERVICE_METADATA_IDENTIFIER_ANNOTATION = "pdok.nl/wms-service-metadata-uuid" +const ServiceMetatdataIdentifierAnnotation = "pdok.nl/wms-service-metadata-uuid" // ConvertTo converts this WMS (v2beta1) to the Hub version (v3). func (src *WMS) ConvertTo(dstRaw conversion.Hub) error { @@ -55,7 +55,7 @@ func V3HubFromV2(src *WMS, target *pdoknlv3.WMS) { dst.Annotations = make(map[string]string) } - dst.Annotations[SERVICE_METADATA_IDENTIFIER_ANNOTATION] = src.Spec.Service.MetadataIdentifier + dst.Annotations[ServiceMetatdataIdentifierAnnotation] = src.Spec.Service.MetadataIdentifier // Set LifeCycle if defined if src.Spec.Kubernetes.Lifecycle != nil && src.Spec.Kubernetes.Lifecycle.TTLInDays != nil { @@ -179,7 +179,7 @@ func (dst *WMS) ConvertFrom(srcRaw conversion.Hub) error { // TODO unable to fill in MetadataIdentifier here until we know how to handle non inspire services } - uuid, ok := src.Annotations[SERVICE_METADATA_IDENTIFIER_ANNOTATION] + uuid, ok := src.Annotations[ServiceMetatdataIdentifierAnnotation] if service.MetadataIdentifier == "00000000-0000-0000-0000-000000000000" && ok { service.MetadataIdentifier = uuid } diff --git a/api/v2beta1/wms_conversion_test.go b/api/v2beta1/wms_conversion_test.go index 08ac014..d184e37 100644 --- a/api/v2beta1/wms_conversion_test.go +++ b/api/v2beta1/wms_conversion_test.go @@ -8,6 +8,7 @@ import ( ) func TestV2ToV3(t *testing.T) { + //nolint:misspell input := "apiVersion: pdok.nl/v2beta1\nkind: WMS\nmetadata:\n name: rws-nwbwegen-v1-0\n labels:\n dataset-owner: rws\n dataset: nwbwegen\n service-version: v1_0\n service-type: wms\n annotations:\n lifecycle-phase: prod\n service-bundle-id: b39c152b-393b-52f5-a50c-e1ffe904b6fb\nspec:\n general:\n datasetOwner: rws\n dataset: nwbwegen\n serviceVersion: v1_0\n kubernetes:\n healthCheck:\n boundingbox: 135134.89,457152.55,135416.03,457187.82\n resources:\n limits:\n ephemeralStorage: 1535Mi\n memory: 4G\n requests:\n cpu: 2000m\n ephemeralStorage: 1535Mi\n memory: 4G\n options:\n automaticCasing: true\n disableWebserviceProxy: false\n includeIngress: true\n validateRequests: true\n service:\n title: NWB - Wegen WMS\n abstract:\n Dit is de web map service van het Nationaal Wegen Bestand (NWB) - wegen.\n Deze dataset bevat alleen de wegvakken en hectometerpunten. Het Nationaal Wegen\n Bestand - Wegen is een digitaal geografisch bestand van alle wegen in Nederland.\n Opgenomen zijn alle wegen die worden beheerd door wegbeheerders als het Rijk,\n provincies, gemeenten en waterschappen, echter alleen voor zover deze zijn voorzien\n van een straatnaam of nummer.\n authority:\n name: rws\n url: https://www.rijkswaterstaat.nl\n dataEPSG: EPSG:28992\n extent: -59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961\n inspire: true\n keywords:\n - Vervoersnetwerken\n - Menselijke gezondheid en veiligheid\n - Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai)\n - Nationaal\n - Voertuigen\n - Verkeer\n - Wegvakken\n - Hectometerpunten\n - HVD\n - Mobiliteit\n stylingAssets:\n configMapRefs:\n - name: includes\n keys:\n - nwb_wegen_hectopunten.symbol\n - hectopunten.style\n - wegvakken.style\n blobKeys:\n - resources/fonts/liberation-sans.ttf\n layers:\n - abstract:\n Deze laag bevat de wegvakken uit het Nationaal Wegen bestand (NWB)\n en geeft gedetailleerde informatie per wegvak zoals straatnaam, wegnummer,\n routenummer, wegbeheerder, huisnummers, enz. weer.\n data:\n gpkg:\n columns:\n - objectid\n - wvk_id\n - wvk_begdat\n - jte_id_beg\n - jte_id_end\n - wegbehsrt\n - wegnummer\n - wegdeelltr\n - hecto_lttr\n - bst_code\n - rpe_code\n - admrichtng\n - rijrichtng\n - stt_naam\n - stt_bron\n - wpsnaam\n - gme_id\n - gme_naam\n - hnrstrlnks\n - hnrstrrhts\n - e_hnr_lnks\n - e_hnr_rhts\n - l_hnr_lnks\n - l_hnr_rhts\n - begafstand\n - endafstand\n - beginkm\n - eindkm\n - pos_tv_wol\n - wegbehcode\n - wegbehnaam\n - distrcode\n - distrnaam\n - dienstcode\n - dienstnaam\n - wegtype\n - wgtype_oms\n - routeltr\n - routenr\n - routeltr2\n - routenr2\n - routeltr3\n - routenr3\n - routeltr4\n - routenr4\n - wegnr_aw\n - wegnr_hmp\n - geobron_id\n - geobron_nm\n - bronjaar\n - openlr\n - bag_orl\n - frc\n - fow\n - alt_naam\n - alt_nr\n - rel_hoogte\n - st_lengthshape\n geometryType: MultiLineString\n blobKey: geopackages/rws/nwbwegen/410a6d1e-e767-41b4-ba8d-9e1e955dd013/1/nwb_wegen.gpkg\n table: wegvakken\n datasetMetadataIdentifier: a9b7026e-0a81-4813-93bd-ba49e6f28502\n keywords:\n - Vervoersnetwerken\n - Menselijke gezondheid en veiligheid\n - Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai)\n - Nationaal\n - Voertuigen\n - Verkeer\n - Wegvakken\n maxScale: 50000.0\n minScale: 1.0\n name: wegvakken\n sourceMetadataIdentifier: 8f0497f0-dbd7-4bee-b85a-5fdec484a7ff\n styles:\n - name: wegvakken\n title: NWB - Wegvakken\n visualization: wegvakken.style\n title: Wegvakken\n visible: true\n - abstract:\n Deze laag bevat de hectopunten uit het Nationaal Wegen Bestand (NWB)\n en geeft gedetailleerde informatie per hectopunt zoals hectometrering, afstand,\n zijde en hectoletter weer.\n data:\n gpkg:\n columns:\n - objectid\n - hectomtrng\n - afstand\n - wvk_id\n - wvk_begdat\n - zijde\n - hecto_lttr\n geometryType: MultiPoint\n blobKey: geopackages/rws/nwbwegen/410a6d1e-e767-41b4-ba8d-9e1e955dd013/1/nwb_wegen.gpkg\n table: hectopunten\n datasetMetadataIdentifier: a9b7026e-0a81-4813-93bd-ba49e6f28502\n keywords:\n - Vervoersnetwerken\n - Menselijke gezondheid en veiligheid\n - Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai)\n - Nationaal\n - Voertuigen\n - Verkeer\n - Hectometerpunten\n maxScale: 50000.0\n minScale: 1.0\n name: hectopunten\n sourceMetadataIdentifier: 8f0497f0-dbd7-4bee-b85a-5fdec484a7ff\n styles:\n - name: hectopunten\n title: NWB - Hectopunten\n visualization: hectopunten.style\n title: Hectopunten\n visible: true\n metadataIdentifier: f2437a92-ddd3-4777-a1bc-fdf4b4a7fcb8\n" var v2wms WMS err := yaml.Unmarshal([]byte(input), &v2wms) diff --git a/api/v2beta1/wms_types.go b/api/v2beta1/wms_types.go index 9428f2c..065cde3 100644 --- a/api/v2beta1/wms_types.go +++ b/api/v2beta1/wms_types.go @@ -54,21 +54,22 @@ type WMSSpec struct { // WMSService is the struct for all service level fields type WMSService struct { - Inspire bool `json:"inspire"` - Title string `json:"title"` - Abstract string `json:"abstract"` - AccessConstraints string `json:"accessConstraints"` - Keywords []string `json:"keywords"` - MetadataIdentifier string `json:"metadataIdentifier"` - Authority Authority `json:"authority"` - Layers []WMSLayer `json:"layers"` - DataEPSG string `json:"dataEPSG"` - Extent *string `json:"extent,omitempty"` - Maxsize *float64 `json:"maxSize,omitempty"` - Resolution *int `json:"resolution,omitempty"` - DefResolution *int `json:"defResolution,omitempty"` - StylingAssets *StylingAssets `json:"stylingAssets,omitempty"` - Mapfile *Mapfile `json:"mapfile,omitempty"` + Inspire bool `json:"inspire"` + Title string `json:"title"` + Abstract string `json:"abstract"` + AccessConstraints string `json:"accessConstraints"` + Keywords []string `json:"keywords"` + MetadataIdentifier string `json:"metadataIdentifier"` + Authority Authority `json:"authority"` + Layers []WMSLayer `json:"layers"` + //nolint:tagliatelle + DataEPSG string `json:"dataEPSG"` + Extent *string `json:"extent,omitempty"` + Maxsize *float64 `json:"maxSize,omitempty"` + Resolution *int `json:"resolution,omitempty"` + DefResolution *int `json:"defResolution,omitempty"` + StylingAssets *StylingAssets `json:"stylingAssets,omitempty"` + Mapfile *Mapfile `json:"mapfile,omitempty"` } // WMSLayer is the struct for all layer level fields diff --git a/api/v3/shared_types.go b/api/v3/shared_types.go index 9c1f3d3..48427b3 100644 --- a/api/v3/shared_types.go +++ b/api/v3/shared_types.go @@ -36,6 +36,8 @@ type WMSWFS interface { // Sha1 hash of the objects name ID() string URLPath() string + + GeoPackages() []*Gpkg } type Mapfile struct { @@ -43,12 +45,24 @@ type Mapfile struct { } type Options struct { - IncludeIngress bool `json:"includeIngress"` - AutomaticCasing bool `json:"automaticCasing"` - ValidateRequests *bool `json:"validateRequests,omitempty"` - RewriteGroupToDataLayers *bool `json:"rewriteGroupToDataLayers,omitempty"` - DisableWebserviceProxy *bool `json:"disableWebserviceProxy,omitempty"` - PrefetchData *bool `json:"prefetchData,omitempty"` + // +kubebuilder:default:=true + IncludeIngress bool `json:"includeIngress"` + + // +kubebuilder:default:=true + AutomaticCasing bool `json:"automaticCasing"` + + // +kubebuilder:default:=true + ValidateRequests *bool `json:"validateRequests,omitempty"` + + // +kubebuilder:default:=false + RewriteGroupToDataLayers *bool `json:"rewriteGroupToDataLayers,omitempty"` + + // +kubebuilder:default:=false + DisableWebserviceProxy *bool `json:"disableWebserviceProxy,omitempty"` + + // +kubebuilder:default:=true + PrefetchData *bool `json:"prefetchData,omitempty"` + ValidateChildStyleNameEqual *bool `json:"validateChildStyleNameEqual,omitempty"` } @@ -108,7 +122,13 @@ func SetHost(url string) { host = strings.TrimSuffix(url, "/") } -func GetHost() string { +func GetHost(includeProtocol bool) string { + if includeProtocol { + return host + } else if strings.HasPrefix(host, "http") { + return strings.Split(host, "://")[1] + } + return host } diff --git a/api/v3/wfs_types.go b/api/v3/wfs_types.go index 7835803..94d5c95 100644 --- a/api/v3/wfs_types.go +++ b/api/v3/wfs_types.go @@ -78,6 +78,8 @@ type WFSSpec struct { } type WFSService struct { + // Geonovum subdomein + // +kubebuilder:validation:MinLength:=1 Prefix string `json:"prefix"` URL string `json:"url"` Inspire *Inspire `json:"inspire,omitempty"` @@ -155,3 +157,15 @@ func (wfs *WFS) ID() string { func (wfs *WFS) URLPath() string { return wfs.Spec.Service.URL } + +func (wfs *WFS) GeoPackages() []*Gpkg { + gpkgs := make([]*Gpkg, 0) + + for _, ft := range wfs.Spec.Service.FeatureTypes { + if ft.Data.Gpkg != nil { + gpkgs = append(gpkgs, ft.Data.Gpkg) + } + } + + return gpkgs +} diff --git a/api/v3/wms_types.go b/api/v3/wms_types.go index 71ab9cd..a030227 100644 --- a/api/v3/wms_types.go +++ b/api/v3/wms_types.go @@ -65,15 +65,16 @@ type WMSService struct { OwnerInfoRef string `json:"ownerInfoRef"` Fees *string `json:"fees,omitempty"` // +kubebuilder:default="https://creativecommons.org/publicdomain/zero/1.0/deed.nl" - AccessConstraints string `json:"accessConstraints"` - MaxSize *int32 `json:"maxSize,omitempty"` - Inspire *Inspire `json:"inspire,omitempty"` - DataEPSG string `json:"dataEPSG"` - Resolution *int32 `json:"resolution,omitempty"` - DefResolution *int32 `json:"defResolution,omitempty"` - StylingAssets *StylingAssets `json:"stylingAssets,omitempty"` - Mapfile *Mapfile `json:"mapfile,omitempty"` - Layer Layer `json:"layer"` + AccessConstraints string `json:"accessConstraints"` + MaxSize *int32 `json:"maxSize,omitempty"` + Inspire *Inspire `json:"inspire,omitempty"` + //nolint:tagliatelle + DataEPSG string `json:"dataEPSG"` + Resolution *int32 `json:"resolution,omitempty"` + DefResolution *int32 `json:"defResolution,omitempty"` + StylingAssets *StylingAssets `json:"stylingAssets,omitempty"` + Mapfile *Mapfile `json:"mapfile,omitempty"` + Layer Layer `json:"layer"` } type StylingAssets struct { @@ -178,7 +179,7 @@ func (wmsService *WMSService) GetBoundingBox() WMSBoundingBox { allLayers := wmsService.GetAllLayers() for _, layer := range allLayers { - if layer.BoundingBoxes != nil && len(layer.BoundingBoxes) > 0 { + if len(layer.BoundingBoxes) > 0 { for _, bbox := range wmsService.Layer.BoundingBoxes { if boundingBox == nil { boundingBox = &bbox @@ -191,18 +192,17 @@ func (wmsService *WMSService) GetBoundingBox() WMSBoundingBox { if boundingBox != nil { return *boundingBox - } else { - return WMSBoundingBox{ - CRS: "EPSG:28992", - BBox: shared_model.BBox{ - MinX: "-25000", - MaxX: "280000", - MinY: "250000", - MaxY: "860000", - }, - } } + return WMSBoundingBox{ + CRS: "EPSG:28992", + BBox: shared_model.BBox{ + MinX: "-25000", + MaxX: "280000", + MinY: "250000", + MaxY: "860000", + }, + } } type AnnotatedLayer struct { @@ -281,11 +281,11 @@ func (layer *Layer) GetParent(candidateLayer *Layer) *Layer { for _, childLayer := range *candidateLayer.Layers { if childLayer.Name == layer.Name { return candidateLayer - } else { - parent := layer.GetParent(&childLayer) - if parent != nil { - return parent - } + } + + parent := layer.GetParent(&childLayer) + if parent != nil { + return parent } } return nil @@ -447,3 +447,25 @@ func (wms *WMS) ID() string { func (wms *WMS) URLPath() string { return wms.Spec.Service.URL } + +func (wms *WMS) GeoPackages() []*Gpkg { + gpkgs := make([]*Gpkg, 0) + + if wms.Spec.Service.Layer.Layers != nil { + for _, layer := range *wms.Spec.Service.Layer.Layers { + if layer.Data != nil { + if layer.Data.Gpkg != nil { + gpkgs = append(gpkgs, layer.Data.Gpkg) + } + } else if layer.Layers != nil { + for _, childLayer := range *layer.Layers { + if childLayer.Data != nil && childLayer.Data.Gpkg != nil { + gpkgs = append(gpkgs, childLayer.Data.Gpkg) + } + } + } + } + } + + return gpkgs +} diff --git a/api/v3/wms_validation.go b/api/v3/wms_validation.go index f75eb86..aa7dde4 100644 --- a/api/v3/wms_validation.go +++ b/api/v3/wms_validation.go @@ -106,6 +106,7 @@ func validateWMS(wms *WMS, warnings *[]string, reasons *[]string) { *reasons = append(*reasons, "layer.boundingBoxes must contain a boundingBox for CRS '"+service.DataEPSG+"' when service.dataEPSG is not 'EPSG:28992'") } + //nolint:nestif if !*layer.Visible { if layer.Title != nil { *warnings = append(*warnings, sharedValidation.FormatValidationWarning("layer.title is not used when layer.visible=false", wms.GroupVersionKind(), wms.GetName())) diff --git a/api/v3/zz_generated.deepcopy.go b/api/v3/zz_generated.deepcopy.go index 3616595..ce8b7cd 100644 --- a/api/v3/zz_generated.deepcopy.go +++ b/api/v3/zz_generated.deepcopy.go @@ -35,6 +35,27 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AnnotatedLayer) DeepCopyInto(out *AnnotatedLayer) { + *out = *in + if in.GroupName != nil { + in, out := &in.GroupName, &out.GroupName + *out = new(string) + **out = **in + } + in.Layer.DeepCopyInto(&out.Layer) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AnnotatedLayer. +func (in *AnnotatedLayer) DeepCopy() *AnnotatedLayer { + if in == nil { + return nil + } + out := new(AnnotatedLayer) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Authority) DeepCopyInto(out *Authority) { *out = *in @@ -240,6 +261,11 @@ func (in *Inspire) DeepCopy() *Inspire { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Layer) DeepCopyInto(out *Layer) { *out = *in + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } if in.Title != nil { in, out := &in.Title, &out.Title *out = new(string) diff --git a/cmd/main.go b/cmd/main.go index ea59479..f9a14aa 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -20,6 +20,7 @@ import ( "crypto/tls" "errors" "flag" + "github.com/pdok/mapserver-operator/internal/controller/mapfilegenerator" smoothoperator "github.com/pdok/smooth-operator/api/v1" traefikiov1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" "os" @@ -51,9 +52,13 @@ const ( defaultMultitoolImage = "acrpdokprodman.azurecr.io/pdok/docker-multitool:0.9.4" defaultMapfileGeneratorImage = "acrpdokprodman.azurecr.io/pdok/mapfile-generator:1.9.5" defaultMapserverImage = "acrpdokprodman.azurecr.io/mirror/docker.io/pdok/mapserver:8.4.0-4-nl" - defaultCapabilitiesGeneratorImage = "acrpdokprodman.azurecr.io/mirror/docker.io/pdok/ogc-capabilities-generator:1.0.0-beta5" + defaultCapabilitiesGeneratorImage = "acrpdokprodman.azurecr.io/mirror/docker.io/pdok/ogc-capabilities-generator:1.0.0-beta7" defaultFeatureinfoGeneratorImage = "acrpdokprodman.azurecr.io/mirror/docker.io/pdok/featureinfo-generator:v1.4.0-beta1" defaultOgcWebserviceProxyImage = "acrpdokprodman.azurecr.io/pdok/ogc-webservice-proxy:0.1.8" + defaultApacheExporterImage = "acrpdokprodman.azurecr.io/mirror/docker.io/lusotycoon/apache-exporter:v0.7.0" + + EnvFalse = "false" + EnvTrue = "true" ) var ( @@ -81,7 +86,8 @@ func main() { var enableHTTP2 bool var tlsOpts []func(*tls.Config) var host string - var multitoolImage, mapfileGeneratorImage, mapserverImage, capabilitiesGeneratorImage, featureinfoGeneratorImage, ogcWebserviceProxyImage string + var mapserverDebugLevel int + var multitoolImage, mapfileGeneratorImage, mapserverImage, capabilitiesGeneratorImage, featureinfoGeneratorImage, ogcWebserviceProxyImage, apacheExporterImage string flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+ "Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.") flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") @@ -106,6 +112,8 @@ func main() { flag.StringVar(&capabilitiesGeneratorImage, "capabilities-generator-image", defaultCapabilitiesGeneratorImage, "The image to use in the capabilities generator init-container.") flag.StringVar(&featureinfoGeneratorImage, "featureinfo-generator-image", defaultFeatureinfoGeneratorImage, "The image to use in the featureinfo generator init-container.") flag.StringVar(&ogcWebserviceProxyImage, "ogc-webservice-proxy-image", defaultOgcWebserviceProxyImage, "The image to use in the ogc webservice proxy container.") + flag.StringVar(&apacheExporterImage, "apache-exporter-image", defaultApacheExporterImage, "The image to use in the apache-exporter container.") + flag.IntVar(&mapserverDebugLevel, "mapserver-debug-level", 0, "Debug level for the mapserver container, between 0 (error only) and 5 (very very verbose).") opts := zap.Options{ Development: true, @@ -120,6 +128,7 @@ func main() { os.Exit(1) } pdoknlv3.SetHost(host) + mapfilegenerator.SetDebugLevel(mapserverDebugLevel) // if the enable-http2 flag is false (the default), http/2 should be disabled // due to its vulnerabilities. More specifically, disabling http/2 will @@ -244,6 +253,7 @@ func main() { CapabilitiesGeneratorImage: capabilitiesGeneratorImage, FeatureinfoGeneratorImage: featureinfoGeneratorImage, OgcWebserviceProxyImage: ogcWebserviceProxyImage, + ApacheExporterImage: apacheExporterImage, }, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "WMS") @@ -257,27 +267,28 @@ func main() { MapfileGeneratorImage: mapfileGeneratorImage, MapserverImage: mapserverImage, CapabilitiesGeneratorImage: capabilitiesGeneratorImage, + ApacheExporterImage: apacheExporterImage, }, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "WFS") os.Exit(1) } - if os.Getenv("ENABLE_WEBHOOKS") != "false" { + if os.Getenv("ENABLE_WEBHOOKS") != EnvFalse { if err = webhookpdoknlv3.SetupWFSWebhookWithManager(mgr); err != nil { setupLog.Error(err, "unable to create webhook", "webhook", "WFS") os.Exit(1) } } - if os.Getenv("ENABLE_WEBHOOKS") != "false" { + if os.Getenv("ENABLE_WEBHOOKS") != EnvFalse { if err = webhookpdoknlv3.SetupWMSWebhookWithManager(mgr); err != nil { setupLog.Error(err, "unable to create webhook", "webhook", "WMS") os.Exit(1) } } - if os.Getenv("ENABLE_WEBHOOKS") != "false" { + if os.Getenv("ENABLE_WEBHOOKS") != EnvFalse { if err = webhookpdoknlv3.SetupWFSWebhookWithManager(mgr); err != nil { setupLog.Error(err, "unable to create webhook", "webhook", "WFS") os.Exit(1) diff --git a/config/crd/bases/pdok.nl_wfs.yaml b/config/crd/bases/pdok.nl_wfs.yaml index 19945d2..6316313 100644 --- a/config/crd/bases/pdok.nl_wfs.yaml +++ b/config/crd/bases/pdok.nl_wfs.yaml @@ -1090,24 +1090,28 @@ spec: ttlInDays: format: int32 type: integer - required: - - ttlInDays type: object options: properties: automaticCasing: + default: true type: boolean disableWebserviceProxy: + default: false type: boolean includeIngress: + default: true type: boolean prefetchData: + default: true type: boolean rewriteGroupToDataLayers: + default: false type: boolean validateChildStyleNameEqual: type: boolean validateRequests: + default: true type: boolean required: - automaticCasing @@ -1398,6 +1402,8 @@ spec: ownerInfoRef: type: string prefix: + description: Geonovum subdomein + minLength: 1 type: string title: type: string diff --git a/config/crd/bases/pdok.nl_wms.yaml b/config/crd/bases/pdok.nl_wms.yaml index 24cd0d6..f1e4355 100644 --- a/config/crd/bases/pdok.nl_wms.yaml +++ b/config/crd/bases/pdok.nl_wms.yaml @@ -1150,24 +1150,28 @@ spec: ttlInDays: format: int32 type: integer - required: - - ttlInDays type: object options: properties: automaticCasing: + default: true type: boolean disableWebserviceProxy: + default: false type: boolean includeIngress: + default: true type: boolean prefetchData: + default: true type: boolean rewriteGroupToDataLayers: + default: false type: boolean validateChildStyleNameEqual: type: boolean validateRequests: + default: true type: boolean required: - automaticCasing diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index ef46bc7..22755e0 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -5,4 +5,4 @@ kind: Kustomization images: - name: controller newName: local-registry:5000/mapserver-operator - newTag: v3.0.23 + newTag: v3.0.10 diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index a2f8572..de757ff 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -63,7 +63,7 @@ spec: args: - --leader-elect - --health-probe-bind-address=:8081 - - --baseurl=https://test.example.nl + - --baseurl=http://localhost:32788 image: controller:latest name: manager ports: [] diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 89cb01d..11e1fd0 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -16,6 +16,14 @@ rules: - list - update - watch +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - watch - apiGroups: - apps resources: diff --git a/go.mod b/go.mod index a792ee9..d71612e 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/pdok/mapserver-operator -go 1.24 +go 1.24.0 toolchain go1.24.2 @@ -11,15 +11,15 @@ require ( github.com/onsi/ginkgo/v2 v2.22.2 github.com/onsi/gomega v1.36.2 github.com/pdok/featureinfo-generator v1.4.0-beta1 - github.com/pdok/ogc-capabilities-generator v1.0.0-beta5 + github.com/pdok/ogc-capabilities-generator v1.0.0-beta6 github.com/pdok/ogc-specifications v1.0.0-beta5 - github.com/pdok/smooth-operator v0.0.10 + github.com/pdok/smooth-operator v0.0.16 github.com/stretchr/testify v1.10.0 github.com/traefik/traefik/v3 v3.3.4 - k8s.io/api v0.32.0 - k8s.io/apimachinery v0.32.0 - k8s.io/client-go v0.32.0 - sigs.k8s.io/controller-runtime v0.20.0 + k8s.io/api v0.32.3 + k8s.io/apimachinery v0.32.3 + k8s.io/client-go v0.32.3 + sigs.k8s.io/controller-runtime v0.20.4 sigs.k8s.io/yaml v1.4.0 ) @@ -37,6 +37,7 @@ require ( github.com/gorilla/mux v1.8.1 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/http-wasm/http-wasm-host-go v0.7.0 // indirect + github.com/klauspost/compress v1.17.11 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/miekg/dns v1.1.62 // indirect @@ -57,20 +58,20 @@ require ( ) require ( - cel.dev/expr v0.19.0 // indirect - github.com/antlr4-go/antlr/v4 v4.13.0 // indirect - github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect + cel.dev/expr v0.19.1 // indirect + github.com/antlr4-go/antlr/v4 v4.13.1 // indirect + github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/emicklei/go-restful/v3 v3.12.0 // indirect - github.com/evanphx/json-patch/v5 v5.9.0 // indirect + github.com/emicklei/go-restful/v3 v3.12.1 // indirect + github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.8.0 // indirect; indirectC github.com/fxamacker/cbor/v2 v2.7.0 // indirect - github.com/go-errors/errors v1.4.2 // indirect + github.com/go-errors/errors v1.5.1 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zapr v1.3.0 // indirect @@ -81,65 +82,65 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/btree v1.1.3 // indirect - github.com/google/cel-go v0.22.0 // indirect + github.com/google/cel-go v0.22.1 // indirect github.com/google/gnostic-models v0.6.9 // indirect github.com/google/go-cmp v0.7.0 github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect github.com/google/uuid v1.6.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/mailru/easyjson v0.7.7 // indirect + github.com/mailru/easyjson v0.9.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_golang v1.21.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/spf13/cobra v1.9.1 // indirect github.com/spf13/pflag v1.0.6 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect github.com/x448/float16 v0.8.4 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect - go.opentelemetry.io/otel v1.34.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect - go.opentelemetry.io/otel/metric v1.34.0 // indirect - go.opentelemetry.io/otel/sdk v1.32.0 // indirect - go.opentelemetry.io/otel/trace v1.34.0 // indirect - go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.opentelemetry.io/otel v1.35.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 // indirect + go.opentelemetry.io/otel/metric v1.35.0 // indirect + go.opentelemetry.io/otel/sdk v1.35.0 // indirect + go.opentelemetry.io/otel/trace v1.35.0 // indirect + go.opentelemetry.io/proto/otlp v1.5.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/exp v0.0.0-20241210194714-1829a127f884 // indirect - golang.org/x/net v0.37.0 // indirect - golang.org/x/oauth2 v0.26.0 // indirect + golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e // indirect + golang.org/x/net v0.38.0 // indirect + golang.org/x/oauth2 v0.28.0 // indirect golang.org/x/sync v0.12.0 // indirect golang.org/x/sys v0.31.0 // indirect golang.org/x/term v0.30.0 // indirect golang.org/x/text v0.23.0 // indirect - golang.org/x/time v0.10.0 // indirect + golang.org/x/time v0.11.0 // indirect golang.org/x/tools v0.31.0 - gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250219182151-9fdb1cabc7b2 // indirect - google.golang.org/grpc v1.70.0 // indirect - google.golang.org/protobuf v1.36.5 // indirect + gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect + google.golang.org/grpc v1.71.1 // indirect + google.golang.org/protobuf v1.36.6 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.32.0 // indirect - k8s.io/apiserver v0.32.0 // indirect - k8s.io/component-base v0.32.0 // indirect + gopkg.in/yaml.v3 v3.0.1 + k8s.io/apiextensions-apiserver v0.32.3 // indirect + k8s.io/apiserver v0.32.3 // indirect + k8s.io/component-base v0.32.3 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 // indirect - k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 - sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 // indirect - sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect + k8s.io/utils v0.0.0-20241210054802-24370beab758 + sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.1 // indirect + sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect sigs.k8s.io/kustomize/api v0.19.0 // indirect sigs.k8s.io/kustomize/kyaml v0.19.0 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect ) diff --git a/go.sum b/go.sum index 480ce1d..e41b868 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,11 @@ -cel.dev/expr v0.19.0 h1:lXuo+nDhpyJSpWxpPVi5cPUwzKb+dsdOiw6IreM5yt0= -cel.dev/expr v0.19.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw= +cel.dev/expr v0.19.1 h1:NciYrtDRIR0lNCnH1LFJegdjspNx9fI59O7TWcua/W4= +cel.dev/expr v0.19.1/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw= github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= -github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= -github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ= +github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.44.327 h1:ZS8oO4+7MOBLhkdwIhgtVeDzCeWOlTfKJS7EgggbIEY= github.com/aws/aws-sdk-go v1.44.327/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -18,6 +18,9 @@ github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK3 github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= +github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -26,12 +29,12 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 h1:clC1lXBpe2kTj2VHdaIu9ajZQe4kcEY9j0NsnDDBZ3o= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= -github.com/emicklei/go-restful/v3 v3.12.0 h1:y2DdzBAURM29NFF94q6RaY4vjIH1rtwDapwQtU84iWk= -github.com/emicklei/go-restful/v3 v3.12.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU= +github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= -github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= +github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= @@ -40,8 +43,8 @@ github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-acme/lego/v4 v4.22.2 h1:ck+HllWrV/rZGeYohsKQ5iKNnU/WAZxwOdiu6cxky+0= github.com/go-acme/lego/v4 v4.22.2/go.mod h1:E2FndyI3Ekv0usNJt46mFb9LVpV/XBYT+4E3tz02Tzo= -github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= -github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= +github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= @@ -71,8 +74,8 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/cel-go v0.22.0 h1:b3FJZxpiv1vTMo2/5RDUqAHPxkT8mmMfJIrq1llbf7g= -github.com/google/cel-go v0.22.0/go.mod h1:BuznPXXfQDpXKWQ9sPW3TzlAJN5zzFe+i9tIs0yC4s8= +github.com/google/cel-go v0.22.1 h1:AfVXx3chM2qwoSbM7Da8g8hX8OVSkBFwX+rz2+PcK40= +github.com/google/cel-go v0.22.1/go.mod h1:BuznPXXfQDpXKWQ9sPW3TzlAJN5zzFe+i9tIs0yC4s8= github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -93,8 +96,10 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 h1:ad0vkEBuk23VJzZR9nkLVG0YAoN9coASF1GusYX6AlU= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0/go.mod h1:igFoXX2ELCW06bol23DWPB5BEWfZISOzSP5K2sbLea0= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/http-wasm/http-wasm-host-go v0.7.0 h1:+1KrRyOO6tWiDB24QrtSYyDmzFLBBs3jioKaUT0mq1c= @@ -110,12 +115,16 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= +github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= @@ -140,23 +149,23 @@ github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaR github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pdok/featureinfo-generator v1.4.0-beta1 h1:ZZO5OtK7yW5ozXFrl1OaxKl0MK3XF5YGFh2692JZVN8= github.com/pdok/featureinfo-generator v1.4.0-beta1/go.mod h1:02Ryu7ZRkeha8SCfS6VYWCdKYZh0llskrfFgp6xRCjk= -github.com/pdok/ogc-capabilities-generator v1.0.0-beta5 h1:nwkIbFcUW4FIYnf6fLfzpkaIdolQoEhH7yyS8KXNt/g= -github.com/pdok/ogc-capabilities-generator v1.0.0-beta5/go.mod h1:qG2auFy7MDL8Zp1eOfdaUJat+jNW5oLGVd+g7Mbth4Q= +github.com/pdok/ogc-capabilities-generator v1.0.0-beta6 h1:yn0ZyMruJ2gmdx7E78LEamtmsxMkFPjFcZYk12mNtcE= +github.com/pdok/ogc-capabilities-generator v1.0.0-beta6/go.mod h1:slk89sAgmWU5NCIKwGyciQWnm0RHmwhJYQ431E2CwSk= github.com/pdok/ogc-specifications v1.0.0-beta5 h1:j7JrXUeW55mVU9ZmJ67r8V6DhbKdgTDiGE1YKFpRWx4= github.com/pdok/ogc-specifications v1.0.0-beta5/go.mod h1:YDngwkwrWOfc5MYnEYseiv97K1Y9bZXlVzwi/8EaIl8= -github.com/pdok/smooth-operator v0.0.10 h1:dv5ua20wB62fcYiV9UznOMB5GjxpVLWqEzqBDZZO014= -github.com/pdok/smooth-operator v0.0.10/go.mod h1:oZWFuIKJGjN/C6ocgMNfMZ7SbLQi+N0qaWj7j95Wdec= +github.com/pdok/smooth-operator v0.0.16 h1:1vurI2TPDHmTaTu0YeG1B9mIIa5MT6GPWhixiZ/styg= +github.com/pdok/smooth-operator v0.0.16/go.mod h1:ohDqrUnmS7wK8TrNHJnFS/mDgf26Yhb8mtRBX3ixdr4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= -github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk= +github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= -github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= +github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= @@ -191,38 +200,46 @@ github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcY github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.etcd.io/etcd/api/v3 v3.5.16 h1:WvmyJVbjWqK4R1E+B12RRHz3bRGy9XVfh++MgbN+6n0= +go.etcd.io/etcd/api/v3 v3.5.16/go.mod h1:1P4SlIP/VwkDmGo3OlOD7faPeP8KDIFhqvciH5EfN28= +go.etcd.io/etcd/client/pkg/v3 v3.5.16 h1:ZgY48uH6UvB+/7R9Yf4x574uCO3jIx0TRDyetSfId3Q= +go.etcd.io/etcd/client/pkg/v3 v3.5.16/go.mod h1:V8acl8pcEK0Y2g19YlOV9m9ssUe6MgiDSobSoaBAM0E= +go.etcd.io/etcd/client/v3 v3.5.16 h1:sSmVYOAHeC9doqi0gv7v86oY/BTld0SEFGaxsU9eRhE= +go.etcd.io/etcd/client/v3 v3.5.16/go.mod h1:X+rExSGkyqxvu276cr2OwPLBaeqFu1cIl4vmRjAD/50= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/collector/pdata v1.10.0 h1:oLyPLGvPTQrcRT64ZVruwvmH/u3SHTfNo01pteS4WOE= go.opentelemetry.io/collector/pdata v1.10.0/go.mod h1:IHxHsp+Jq/xfjORQMDJjSH6jvedOSTOyu3nbxqhWSYE= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= -go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= -go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= +go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0 h1:WzNab7hOOLzdDF/EoWCt4glhrbMPVMOO5JYTmpz36Ls= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0/go.mod h1:hKvJwTzJdp90Vh7p6q/9PAOd55dI6WA6sWj62a/JvSs= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0 h1:S+LdBGiQXtJdowoJoQPEtI52syEP/JYBUpjO49EQhV8= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0/go.mod h1:5KXybFvPGds3QinJWQT7pmXf+TN5YIa7CNYObWRkj50= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 h1:j9+03ymgYhPKmeXGk5Zu+cIZOlVzd9Zv7QIiyItjFBU= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0/go.mod h1:Y5+XiUG4Emn1hTfciPzGPJaSI+RpDts6BnCIir0SLqk= go.opentelemetry.io/otel/log v0.8.0 h1:egZ8vV5atrUWUbnSsHn6vB8R21G2wrKqNiDt3iWertk= go.opentelemetry.io/otel/log v0.8.0/go.mod h1:M9qvDdUTRCopJcGRKg57+JSQ9LgLBrwwfC32epk5NX8= -go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= -go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= -go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= -go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= +go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= +go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= +go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= go.opentelemetry.io/otel/sdk/log v0.8.0 h1:zg7GUYXqxk1jnGF/dTdLPrK06xJdrXgqgFLnI4Crxvs= go.opentelemetry.io/otel/sdk/log v0.8.0/go.mod h1:50iXr0UVwQrYS45KbruFrEt4LvAdCaWWgIrsN3ZQggo= -go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= -go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= -go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= -go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= -go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= -go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= +go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= +go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= +go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= +go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= +go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -235,8 +252,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= -golang.org/x/exp v0.0.0-20241210194714-1829a127f884 h1:Y/Mj/94zIQQGHVSv1tTtQBDaQaJe62U9bkDZKKyhPCU= -golang.org/x/exp v0.0.0-20241210194714-1829a127f884/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= +golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e h1:4qufH0hlUYs6AO6XmZC3GqfDPGSXHVXUFR6OND+iJX4= +golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -250,11 +267,11 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= -golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE= -golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= +golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -286,8 +303,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= -golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4= -golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= +golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -299,17 +316,17 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= -gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= +gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0= +gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q= -google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250219182151-9fdb1cabc7b2 h1:DMTIbak9GhdaSxEjvVzAeNZvyc03I61duqNbnm3SU0M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250219182151-9fdb1cabc7b2/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= -google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= -google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 h1:hE3bRWtU6uceqlh4fhrSnUyjKHMKB9KrTLLG+bc0ddM= +google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463/go.mod h1:U90ffi8eUL9MwPcrJylN5+Mk2v3vuPDptd5yyNUiRR8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= +google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= @@ -321,35 +338,37 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE= -k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0= -k8s.io/apiextensions-apiserver v0.32.0 h1:S0Xlqt51qzzqjKPxfgX1xh4HBZE+p8KKBq+k2SWNOE0= -k8s.io/apiextensions-apiserver v0.32.0/go.mod h1:86hblMvN5yxMvZrZFX2OhIHAuFIMJIZ19bTvzkP+Fmw= -k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg= -k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= -k8s.io/apiserver v0.32.0 h1:VJ89ZvQZ8p1sLeiWdRJpRD6oLozNZD2+qVSLi+ft5Qs= -k8s.io/apiserver v0.32.0/go.mod h1:HFh+dM1/BE/Hm4bS4nTXHVfN6Z6tFIZPi649n83b4Ag= -k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8= -k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8= -k8s.io/component-base v0.32.0 h1:d6cWHZkCiiep41ObYQS6IcgzOUQUNpywm39KVYaUqzU= -k8s.io/component-base v0.32.0/go.mod h1:JLG2W5TUxUu5uDyKiH2R/7NnxJo1HlPoRIIbVLkK5eM= +k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= +k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k= +k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY= +k8s.io/apiextensions-apiserver v0.32.3/go.mod h1:8YwcvVRMVzw0r1Stc7XfGAzB/SIVLunqApySV5V7Dss= +k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U= +k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= +k8s.io/apiserver v0.32.3 h1:kOw2KBuHOA+wetX1MkmrxgBr648ksz653j26ESuWNY8= +k8s.io/apiserver v0.32.3/go.mod h1:q1x9B8E/WzShF49wh3ADOh6muSfpmFL0I2t+TG0Zdgc= +k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU= +k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY= +k8s.io/component-base v0.32.3 h1:98WJvvMs3QZ2LYHBzvltFSeJjEx7t5+8s71P7M74u8k= +k8s.io/component-base v0.32.3/go.mod h1:LWi9cR+yPAv7cu2X9rZanTiFKB2kHA+JjmhkKjCZRpI= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 h1:hcha5B1kVACrLujCKLbr8XWMxCxzQx42DY8QKYJrDLg= k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas= -k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= -k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 h1:CPT0ExVicCzcpeN4baWEV2ko2Z/AsiZgEdwgcfwLgMo= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= -sigs.k8s.io/controller-runtime v0.20.0 h1:jjkMo29xEXH+02Md9qaVXfEIaMESSpy3TBWPrsfQkQs= -sigs.k8s.io/controller-runtime v0.20.0/go.mod h1:BrP3w158MwvB3ZbNpaAcIKkHQ7YGpYnzpoSTZ8E14WU= -sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= -sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= +k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0= +k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.1 h1:uOuSLOMBWkJH0TWa9X6l+mj5nZdm6Ay6Bli8HL8rNfk= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.1/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= +sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU= +sigs.k8s.io/controller-runtime v0.20.4/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/kustomize/api v0.19.0 h1:F+2HB2mU1MSiR9Hp1NEgoU2q9ItNOaBJl0I4Dlus5SQ= sigs.k8s.io/kustomize/api v0.19.0/go.mod h1:/BbwnivGVcBh1r+8m3tH1VNxJmHSk1PzP5fkP6lbL1o= sigs.k8s.io/kustomize/kyaml v0.19.0 h1:RFge5qsO1uHhwJsu3ipV7RNolC7Uozc0jUBC/61XSlA= sigs.k8s.io/kustomize/kyaml v0.19.0/go.mod h1:FeKD5jEOH+FbZPpqUghBP8mrLjJ3+zD3/rf9NNu1cwY= -sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= -sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= +sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016 h1:kXv6kKdoEtedwuqMmkqhbkgvYKeycVbC8+iPCP9j5kQ= +sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc= +sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/internal/controller/blobdownload/blob_download.go b/internal/controller/blobdownload/blob_download.go index 7c13146..fd3c7f5 100644 --- a/internal/controller/blobdownload/blob_download.go +++ b/internal/controller/blobdownload/blob_download.go @@ -4,6 +4,7 @@ import ( _ "embed" "fmt" smoothoperatorutils "github.com/pdok/smooth-operator/pkg/util" + "k8s.io/utils/strings/slices" "regexp" "strings" @@ -30,10 +31,28 @@ func GetScript() string { } func GetBlobDownloadInitContainer[O pdoknlv3.WMSWFS](obj O, image, blobsConfigName, blobsSecretName, srvDir string) (*corev1.Container, error) { + blobkeys := []string{} + for _, gpkg := range obj.GeoPackages() { + // Deduplicate blobkeys to prevent double downloads + if !slices.Contains(blobkeys, gpkg.BlobKey) { + blobkeys = append(blobkeys, gpkg.BlobKey) + } + } + initContainer := corev1.Container{ Name: "blob-download", Image: image, ImagePullPolicy: corev1.PullIfNotPresent, + Env: []corev1.EnvVar{ + { + Name: "GEOPACKAGE_TARGET_PATH", + Value: "/srv/data/gpkg", + }, + { + Name: "GEOPACKAGE_DOWNLOAD_LIST", + Value: strings.Join(blobkeys, ";"), + }, + }, EnvFrom: []corev1.EnvFromSource{ // Todo add this ConfigMap utils.NewEnvFromSource(utils.EnvFromSourceTypeConfigMap, blobsConfigName), @@ -71,7 +90,7 @@ func GetBlobDownloadInitContainer[O pdoknlv3.WMSWFS](obj O, image, blobsConfigNa if options.PrefetchData != nil && *options.PrefetchData { mount := corev1.VolumeMount{ Name: mapserver.ConfigMapBlobDownloadVolumeName, - MountPath: "/src/scripts", + MountPath: "/srv/scripts", ReadOnly: true, } initContainer.VolumeMounts = append(initContainer.VolumeMounts, mount) @@ -143,7 +162,7 @@ func downloadStylingAssets(sb *strings.Builder, wms *pdoknlv3.WMS) error { return nil } - re := regexp.MustCompile(".*\\.(ttf)$") + re := regexp.MustCompile(`.*\.(ttf)$`) for _, blobKey := range wms.Spec.Service.StylingAssets.BlobKeys { fileName, err := getFilenameFromBlobKey(blobKey) if err != nil { diff --git a/internal/controller/blobdownload/gpkg_download.sh b/internal/controller/blobdownload/gpkg_download.sh index d6d5681..8d036a0 100644 --- a/internal/controller/blobdownload/gpkg_download.sh +++ b/internal/controller/blobdownload/gpkg_download.sh @@ -61,7 +61,7 @@ function download() { fi local gpkg=$1 - local file={{ gpkg_path }}/$2 + local file=$GEOPACKAGE_TARGET_PATH/$2 local url=${BLOBS_ENDPOINT}/${gpkg} download_gpkg $gpkg $file $url @@ -112,12 +112,17 @@ function download_all() { local start_time=$(date '+%s') # create target location if not exists - mkdir -p {{ gpkg_path }} - chown 999:999 {{ gpkg_path }} - -{% for blobKey in (service.featureTypes if type == 'wfs' else service.layers if type == 'wms' else []) | json_query('[].data.gpkg.blobKey') | unique %} - download {{ blobKey }} {{ blobKey.split('/') | last }}; -{% endfor %} + mkdir -p $GEOPACKAGE_TARGET_PATH + chown 999:999 $GEOPACKAGE_TARGET_PATH + + # Download all geopackages from GEOPACKAGE_DOWNLOAD_LIST + # Example: GEOPACKAGE_DOWNLOAD_LIST=path/1/file.gpkg;path/3/other_file.gpkg + gpkgs=(${GEOPACKAGE_DOWNLOAD_LIST//;/ }) + for gpkg_path in "${gpkgs[@]}" + do + filename=$(basename $gpkg_path) + download $gpkg_path $filename + done echo msg=\"All GeoPackages downloaded\" total_time_seconds=$(expr $(date '+%s') - $start_time) } diff --git a/internal/controller/capabilitiesgenerator/capabilities_generator.go b/internal/controller/capabilitiesgenerator/capabilities_generator.go index 5fbd7ac..2332e03 100644 --- a/internal/controller/capabilitiesgenerator/capabilities_generator.go +++ b/internal/controller/capabilitiesgenerator/capabilities_generator.go @@ -2,15 +2,15 @@ package capabilitiesgenerator import ( "fmt" + "gopkg.in/yaml.v3" pdoknlv3 "github.com/pdok/mapserver-operator/api/v3" "github.com/pdok/mapserver-operator/internal/controller/mapserver" smoothoperatorv1 "github.com/pdok/smooth-operator/api/v1" corev1 "k8s.io/api/core/v1" - yaml "sigs.k8s.io/yaml/goyaml.v3" ) -func GetCapabilitiesGeneratorInitContainer[O pdoknlv3.WMSWFS](obj O, image string) (*corev1.Container, error) { +func GetCapabilitiesGeneratorInitContainer[O pdoknlv3.WMSWFS](_ O, image string) (*corev1.Container, error) { initContainer := corev1.Container{ Name: "capabilities-generator", Image: image, diff --git a/internal/controller/capabilitiesgenerator/capabilities_generator_test.go b/internal/controller/capabilitiesgenerator/capabilities_generator_test.go index b1417e4..bf84b77 100644 --- a/internal/controller/capabilitiesgenerator/capabilities_generator_test.go +++ b/internal/controller/capabilitiesgenerator/capabilities_generator_test.go @@ -91,6 +91,7 @@ services: metadataUrl: href: https://www.nationaalgeoregister.nl/geonetwork/srv/dut/csw?service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&elementsetname=full&id=datadata-data-data-data-datadatadata ` + //nolint:misspell WMSInput = `global: prefix: prefix namespace: http://prefix.geonovum.nl @@ -635,13 +636,13 @@ func TestGetInputForWFS(t *testing.T) { }, ownerInfo: &smoothoperatorv1.OwnerInfo{ Spec: smoothoperatorv1.OwnerInfoSpec{ - NamespaceTemplate: "http://{{prefix}}.geonovum.nl", - MetadataUrls: smoothoperatorv1.MetadataUrls{ - CSW: smoothoperatorv1.MetadataURL{ + NamespaceTemplate: smoothoperatorutils.Pointer("http://{{prefix}}.geonovum.nl"), + MetadataUrls: &smoothoperatorv1.MetadataUrls{ + CSW: &smoothoperatorv1.MetadataURL{ HrefTemplate: "https://www.nationaalgeoregister.nl/geonetwork/srv/dut/csw?service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&elementsetname=full&id={{identifier}}", }, }, - WFS: smoothoperatorv1.WFS{ + WFS: &smoothoperatorv1.WFS{ ServiceProvider: smoothoperatorv1.ServiceProvider{ ProviderName: smoothoperatorutils.Pointer("PDOK"), }, @@ -668,6 +669,7 @@ func TestGetInputForWFS(t *testing.T) { } func TestInputForWMS(t *testing.T) { + //nolint:misspell v2wmsstring := "apiVersion: pdok.nl/v2beta1\nkind: WMS\nmetadata:\n name: rws-nwbwegen-v1-0\n labels:\n dataset-owner: rws\n dataset: nwbwegen\n service-version: v1_0\n service-type: wms\n annotations:\n lifecycle-phase: prod\n service-bundle-id: b39c152b-393b-52f5-a50c-e1ffe904b6fb\nspec:\n general:\n datasetOwner: rws\n dataset: nwbwegen\n serviceVersion: v1_0\n kubernetes:\n healthCheck:\n boundingbox: 135134.89,457152.55,135416.03,457187.82\n resources:\n limits:\n ephemeralStorage: 1535Mi\n memory: 4G\n requests:\n cpu: 2000m\n ephemeralStorage: 1535Mi\n memory: 4G\n options:\n automaticCasing: true\n disableWebserviceProxy: false\n includeIngress: true\n validateRequests: true\n service:\n title: NWB - Wegen WMS\n abstract:\n Dit is de web map service van het Nationaal Wegen Bestand (NWB) - wegen.\n Deze dataset bevat alleen de wegvakken en hectometerpunten. Het Nationaal Wegen\n Bestand - Wegen is een digitaal geografisch bestand van alle wegen in Nederland.\n Opgenomen zijn alle wegen die worden beheerd door wegbeheerders als het Rijk,\n provincies, gemeenten en waterschappen, echter alleen voor zover deze zijn voorzien\n van een straatnaam of nummer.\n authority:\n name: rws\n url: https://www.rijkswaterstaat.nl\n dataEPSG: EPSG:28992\n extent: -59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961\n inspire: true\n keywords:\n - Vervoersnetwerken\n - Menselijke gezondheid en veiligheid\n - Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai)\n - Nationaal\n - Voertuigen\n - Verkeer\n - Wegvakken\n - Hectometerpunten\n - HVD\n - Mobiliteit\n stylingAssets:\n configMapRefs:\n - name: includes\n keys:\n - nwb_wegen_hectopunten.symbol\n - hectopunten.style\n - wegvakken.style\n blobKeys:\n - resources/fonts/liberation-sans.ttf\n layers:\n - abstract:\n Deze laag bevat de wegvakken uit het Nationaal Wegen bestand (NWB)\n en geeft gedetailleerde informatie per wegvak zoals straatnaam, wegnummer,\n routenummer, wegbeheerder, huisnummers, enz. weer.\n data:\n gpkg:\n columns:\n - objectid\n - wvk_id\n - wvk_begdat\n - jte_id_beg\n - jte_id_end\n - wegbehsrt\n - wegnummer\n - wegdeelltr\n - hecto_lttr\n - bst_code\n - rpe_code\n - admrichtng\n - rijrichtng\n - stt_naam\n - stt_bron\n - wpsnaam\n - gme_id\n - gme_naam\n - hnrstrlnks\n - hnrstrrhts\n - e_hnr_lnks\n - e_hnr_rhts\n - l_hnr_lnks\n - l_hnr_rhts\n - begafstand\n - endafstand\n - beginkm\n - eindkm\n - pos_tv_wol\n - wegbehcode\n - wegbehnaam\n - distrcode\n - distrnaam\n - dienstcode\n - dienstnaam\n - wegtype\n - wgtype_oms\n - routeltr\n - routenr\n - routeltr2\n - routenr2\n - routeltr3\n - routenr3\n - routeltr4\n - routenr4\n - wegnr_aw\n - wegnr_hmp\n - geobron_id\n - geobron_nm\n - bronjaar\n - openlr\n - bag_orl\n - frc\n - fow\n - alt_naam\n - alt_nr\n - rel_hoogte\n - st_lengthshape\n geometryType: MultiLineString\n blobKey: geopackages/rws/nwbwegen/410a6d1e-e767-41b4-ba8d-9e1e955dd013/1/nwb_wegen.gpkg\n table: wegvakken\n datasetMetadataIdentifier: a9b7026e-0a81-4813-93bd-ba49e6f28502\n keywords:\n - Vervoersnetwerken\n - Menselijke gezondheid en veiligheid\n - Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai)\n - Nationaal\n - Voertuigen\n - Verkeer\n - Wegvakken\n maxScale: 50000.0\n minScale: 1.0\n name: wegvakken\n sourceMetadataIdentifier: 8f0497f0-dbd7-4bee-b85a-5fdec484a7ff\n styles:\n - name: wegvakken\n title: NWB - Wegvakken\n visualization: wegvakken.style\n title: Wegvakken\n visible: true\n - abstract:\n Deze laag bevat de hectopunten uit het Nationaal Wegen Bestand (NWB)\n en geeft gedetailleerde informatie per hectopunt zoals hectometrering, afstand,\n zijde en hectoletter weer.\n data:\n gpkg:\n columns:\n - objectid\n - hectomtrng\n - afstand\n - wvk_id\n - wvk_begdat\n - zijde\n - hecto_lttr\n geometryType: MultiPoint\n blobKey: geopackages/rws/nwbwegen/410a6d1e-e767-41b4-ba8d-9e1e955dd013/1/nwb_wegen.gpkg\n table: hectopunten\n datasetMetadataIdentifier: a9b7026e-0a81-4813-93bd-ba49e6f28502\n keywords:\n - Vervoersnetwerken\n - Menselijke gezondheid en veiligheid\n - Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai)\n - Nationaal\n - Voertuigen\n - Verkeer\n - Hectometerpunten\n maxScale: 50000.0\n minScale: 1.0\n name: hectopunten\n sourceMetadataIdentifier: 8f0497f0-dbd7-4bee-b85a-5fdec484a7ff\n styles:\n - name: hectopunten\n title: NWB - Hectopunten\n visualization: hectopunten.style\n title: Hectopunten\n visible: true\n metadataIdentifier: f2437a92-ddd3-4777-a1bc-fdf4b4a7fcb8\n" var v2wms v2beta1.WMS err := yaml.Unmarshal([]byte(v2wmsstring), &v2wms) @@ -683,14 +685,14 @@ func TestInputForWMS(t *testing.T) { ownerInfo := smoothoperatorv1.OwnerInfo{ Spec: smoothoperatorv1.OwnerInfoSpec{ - NamespaceTemplate: "http://{{prefix}}.geonovum.nl", - MetadataUrls: smoothoperatorv1.MetadataUrls{ - CSW: smoothoperatorv1.MetadataURL{ + NamespaceTemplate: smoothoperatorutils.Pointer("http://{{prefix}}.geonovum.nl"), + MetadataUrls: &smoothoperatorv1.MetadataUrls{ + CSW: &smoothoperatorv1.MetadataURL{ HrefTemplate: "https://www.nationaalgeoregister.nl/geonetwork/srv/dut/csw?service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&elementsetname=full&id={{identifier}}", }, }, - WMS: smoothoperatorv1.WMS{ - ContactInformation: &smoothoperatorv1.ContactInformation{ + WMS: &smoothoperatorv1.WMS{ + ContactInformation: smoothoperatorv1.ContactInformation{ ContactPersonPrimary: &contactPersonPrimary, ContactPosition: asPtr("pointOfContact"), ContactAddress: &smoothoperatorv1.ContactAddress{ diff --git a/internal/controller/capabilitiesgenerator/mapper.go b/internal/controller/capabilitiesgenerator/mapper.go index 8660c3a..7c3f4ba 100644 --- a/internal/controller/capabilitiesgenerator/mapper.go +++ b/internal/controller/capabilitiesgenerator/mapper.go @@ -13,6 +13,7 @@ import ( "github.com/pdok/ogc-specifications/pkg/wfs200" "github.com/pdok/ogc-specifications/pkg/wsc110" smoothoperatorv1 "github.com/pdok/smooth-operator/api/v1" + smoothoperatorutils "github.com/pdok/smooth-operator/pkg/util" ) const ( @@ -32,7 +33,7 @@ func MapWFSToCapabilitiesGeneratorInput(wfs *pdoknlv3.WFS, ownerInfo *smoothoper Global: capabilitiesgenerator.Global{ Namespace: mapperutils.GetNamespaceURI(wfs.Spec.Service.Prefix, ownerInfo), Prefix: wfs.Spec.Service.Prefix, - Onlineresourceurl: pdoknlv3.GetHost(), + Onlineresourceurl: pdoknlv3.GetHost(true), Path: "/" + pdoknlv3.GetBaseURLPath(wfs), Version: *mapperutils.GetLabelValueByKey(wfs.ObjectMeta.Labels, "service-version"), }, @@ -204,11 +205,11 @@ func mapServiceProvider(provider *smoothoperatorv1.ServiceProvider) (serviceProv } func MapWMSToCapabilitiesGeneratorInput(wms *pdoknlv3.WMS, ownerInfo *smoothoperatorv1.OwnerInfo) (*capabilitiesgenerator.Config, error) { - hostBaseUrl := "https://service.pdok.nl" - canonicalServiceUrl := hostBaseUrl + "/" + pdoknlv3.GetBaseURLPath(wms) + hostBaseURL := "https://service.pdok.nl" + canonicalServiceURL := hostBaseURL + "/" + pdoknlv3.GetBaseURLPath(wms) abstract := mapperutils.EscapeQuotes(wms.Spec.Service.Abstract) - var fees *string = nil + var fees *string if wms.Spec.Service.Fees != nil { feesPtr := mapperutils.EscapeQuotes(*wms.Spec.Service.Fees) fees = &feesPtr @@ -228,7 +229,7 @@ func MapWMSToCapabilitiesGeneratorInput(wms *pdoknlv3.WMS, ownerInfo *smoothoper Global: capabilitiesgenerator.Global{ Namespace: mapperutils.GetNamespaceURI("prefix", ownerInfo), Prefix: "prefix", - Onlineresourceurl: pdoknlv3.GetHost(), + Onlineresourceurl: pdoknlv3.GetHost(true), Path: "/" + pdoknlv3.GetBaseURLPath(wms), Version: *mapperutils.GetLabelValueByKey(wms.ObjectMeta.Labels, "service-version"), }, @@ -241,7 +242,7 @@ func MapWMSToCapabilitiesGeneratorInput(wms *pdoknlv3.WMS, ownerInfo *smoothoper Title: mapperutils.EscapeQuotes(wms.Spec.Service.Title), Abstract: &abstract, KeywordList: &wms130.Keywords{Keyword: wms.Spec.Service.Keywords}, - OnlineResource: wms130.OnlineResource{Href: &hostBaseUrl}, + OnlineResource: wms130.OnlineResource{Href: &hostBaseURL}, ContactInformation: getContactInformation(ownerInfo), Fees: fees, AccessConstraints: &accessContraints, @@ -254,20 +255,20 @@ func MapWMSToCapabilitiesGeneratorInput(wms *pdoknlv3.WMS, ownerInfo *smoothoper Request: wms130.Request{ GetCapabilities: wms130.RequestType{ Format: []string{"text/xml"}, - DCPType: getDcpType(canonicalServiceUrl, false), + DCPType: getDcpType(canonicalServiceURL, false), }, GetMap: wms130.RequestType{ Format: []string{"image/png", "image/jpeg", "image/png; mode=8bit", "image/vnd.jpeg-png", "image/vnd.jpeg-png8"}, - DCPType: getDcpType(canonicalServiceUrl, true), + DCPType: getDcpType(canonicalServiceURL, true), }, GetFeatureInfo: &wms130.RequestType{ Format: []string{"application/json", "application/json; subtype=geojson", "application/vnd.ogc.gml", "text/html", "text/plain", "text/xml", "text/xml; subtype=gml/3.1.1"}, - DCPType: getDcpType(canonicalServiceUrl, true), + DCPType: getDcpType(canonicalServiceURL, true), }, }, Exception: wms130.ExceptionType{Format: []string{"XML", "BLANK"}}, ExtendedCapabilities: nil, - Layer: getLayers(wms, canonicalServiceUrl), + Layer: getLayers(wms, canonicalServiceURL), }, OptionalConstraints: wms130.OptionalConstraints{}, }, @@ -306,11 +307,6 @@ func getContactInformation(ownerInfo *smoothoperatorv1.OwnerInfo) *wms130.Contac } providedContactInformation := ownerInfo.Spec.WMS.ContactInformation - - if providedContactInformation == nil { - return &result - } - if providedContactInformation.ContactPersonPrimary != nil { contactPerson := "" if providedContactInformation.ContactPersonPrimary.ContactPerson != nil { @@ -332,12 +328,12 @@ func getContactInformation(ownerInfo *smoothoperatorv1.OwnerInfo) *wms130.Contac if providedContactInformation.ContactAddress != nil { contactAddressInput := providedContactInformation.ContactAddress contactAddress := wms130.ContactAddress{ - AddressType: pointerValOrDefault(contactAddressInput.AddressType, ""), - Address: pointerValOrDefault(contactAddressInput.Address, ""), - City: pointerValOrDefault(contactAddressInput.City, ""), - StateOrProvince: pointerValOrDefault(contactAddressInput.StateOrProvince, ""), - PostalCode: pointerValOrDefault(contactAddressInput.PostCode, ""), - Country: pointerValOrDefault(contactAddressInput.Country, ""), + AddressType: smoothoperatorutils.PointerVal(contactAddressInput.AddressType, ""), + Address: smoothoperatorutils.PointerVal(contactAddressInput.Address, ""), + City: smoothoperatorutils.PointerVal(contactAddressInput.City, ""), + StateOrProvince: smoothoperatorutils.PointerVal(contactAddressInput.StateOrProvince, ""), + PostalCode: smoothoperatorutils.PointerVal(contactAddressInput.PostCode, ""), + Country: smoothoperatorutils.PointerVal(contactAddressInput.Country, ""), } result.ContactAddress = &contactAddress } @@ -358,7 +354,7 @@ func getDcpType(url string, fillPost bool) *wms130.DCPType { }, } - var post *wms130.Method = nil + var post *wms130.Method if fillPost { post = &get } @@ -375,7 +371,7 @@ func getDcpType(url string, fillPost bool) *wms130.DCPType { return &result } -func getLayers(wms *pdoknlv3.WMS, canonicalUrl string) []wms130.Layer { +func getLayers(wms *pdoknlv3.WMS, canonicalURL string) []wms130.Layer { result := make([]wms130.Layer, 0) referenceLayer := wms.Spec.Service.Layer title := referenceLayer.Title @@ -505,11 +501,11 @@ func getLayers(wms *pdoknlv3.WMS, canonicalUrl string) []wms130.Layer { Resy: 0, }) - var authorityUrl *wms130.AuthorityURL = nil - var identifier *wms130.Identifier = nil + var authorityURL *wms130.AuthorityURL + var identifier *wms130.Identifier if referenceLayer.Authority != nil { - authorityUrl = &wms130.AuthorityURL{ + authorityURL = &wms130.AuthorityURL{ Name: referenceLayer.Authority.Name, OnlineResource: wms130.OnlineResource{ Xlink: nil, @@ -535,7 +531,7 @@ func getLayers(wms *pdoknlv3.WMS, canonicalUrl string) []wms130.Layer { BoundingBox: allDefaultBoundingBoxes, Dimension: nil, Attribution: nil, - AuthorityURL: authorityUrl, + AuthorityURL: authorityURL, Identifier: identifier, MetadataURL: nil, DataURL: nil, @@ -589,7 +585,7 @@ func getLayers(wms *pdoknlv3.WMS, canonicalUrl string) []wms130.Layer { Queryable: asPtr(1), Opaque: nil, Name: layer.Name, - Title: pointerValOrDefault(layer.Title, ""), + Title: smoothoperatorutils.PointerVal(layer.Title, ""), Abstract: layer.Abstract, KeywordList: &wms130.Keywords{ Keyword: layer.Keywords, @@ -599,7 +595,7 @@ func getLayers(wms *pdoknlv3.WMS, canonicalUrl string) []wms130.Layer { BoundingBox: allDefaultBoundingBoxes, Dimension: nil, Attribution: nil, - AuthorityURL: authorityUrl, + AuthorityURL: authorityURL, Identifier: innerIdentifier, MetadataURL: metadataUrls, DataURL: nil, @@ -612,7 +608,7 @@ func getLayers(wms *pdoknlv3.WMS, canonicalUrl string) []wms130.Layer { for _, style := range layer.Styles { newStyle := wms130.Style{ Name: style.Name, - Title: pointerValOrDefault(style.Title, ""), + Title: smoothoperatorutils.PointerVal(style.Title, ""), Abstract: style.Abstract, LegendURL: &wms130.LegendURL{ Width: 78, @@ -621,7 +617,7 @@ func getLayers(wms *pdoknlv3.WMS, canonicalUrl string) []wms130.Layer { OnlineResource: wms130.OnlineResource{ Xlink: nil, Type: asPtr("simple"), - Href: asPtr(canonicalUrl + "/legend/" + *layer.Name + "/" + style.Name + ".png"), + Href: asPtr(canonicalURL + "/legend/" + *layer.Name + "/" + style.Name + ".png"), }, }, StyleSheetURL: nil, @@ -636,14 +632,6 @@ func getLayers(wms *pdoknlv3.WMS, canonicalUrl string) []wms130.Layer { return result } -func pointerValOrDefault[T any](pointer *T, defaultValue T) T { - if pointer != nil { - return *pointer - } else { - return defaultValue - } -} - func asPtr[T any](value T) *T { return &value } diff --git a/internal/controller/featureinfogenerator/mapper.go b/internal/controller/featureinfogenerator/mapper.go index 89624fd..a5462f3 100644 --- a/internal/controller/featureinfogenerator/mapper.go +++ b/internal/controller/featureinfogenerator/mapper.go @@ -62,7 +62,7 @@ func getPropertiesForVector(columns []pdoknlv3.Column) (properties []featureinfo func getPropertiesForRaster(includeClass *bool) (properties []featureinfo.Property) { properties = append(properties, featureinfo.Property{Name: "value_list"}) - if includeClass != nil && *includeClass == true { + if includeClass != nil && *includeClass { properties = append(properties, featureinfo.Property{Name: "class"}) } return diff --git a/internal/controller/legendgenerator/legend_generator_test.go b/internal/controller/legendgenerator/legend_generator_test.go index b4010db..d30ba9c 100644 --- a/internal/controller/legendgenerator/legend_generator_test.go +++ b/internal/controller/legendgenerator/legend_generator_test.go @@ -9,7 +9,7 @@ import ( ) func TestGetConfigMapDataNoLegendFix(t *testing.T) { - + //nolint:misspell v2wmsstring := "apiVersion: pdok.nl/v2beta1\nkind: WMS\nmetadata:\n name: rws-nwbwegen-v1-0\n labels:\n dataset-owner: rws\n dataset: nwbwegen\n service-version: v1_0\n service-type: wms\n annotations:\n lifecycle-phase: prod\n service-bundle-id: b39c152b-393b-52f5-a50c-e1ffe904b6fb\nspec:\n general:\n datasetOwner: rws\n dataset: nwbwegen\n serviceVersion: v1_0\n kubernetes:\n healthCheck:\n boundingbox: 135134.89,457152.55,135416.03,457187.82\n resources:\n limits:\n ephemeralStorage: 1535Mi\n memory: 4G\n requests:\n cpu: 2000m\n ephemeralStorage: 1535Mi\n memory: 4G\n options:\n automaticCasing: true\n disableWebserviceProxy: false\n includeIngress: true\n validateRequests: true\n service:\n title: NWB - Wegen WMS\n abstract:\n Dit is de web map service van het Nationaal Wegen Bestand (NWB) - wegen.\n Deze dataset bevat alleen de wegvakken en hectometerpunten. Het Nationaal Wegen\n Bestand - Wegen is een digitaal geografisch bestand van alle wegen in Nederland.\n Opgenomen zijn alle wegen die worden beheerd door wegbeheerders als het Rijk,\n provincies, gemeenten en waterschappen, echter alleen voor zover deze zijn voorzien\n van een straatnaam of nummer.\n authority:\n name: rws\n url: https://www.rijkswaterstaat.nl\n dataEPSG: EPSG:28992\n extent: -59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961\n inspire: true\n keywords:\n - Vervoersnetwerken\n - Menselijke gezondheid en veiligheid\n - Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai)\n - Nationaal\n - Voertuigen\n - Verkeer\n - Wegvakken\n - Hectometerpunten\n - HVD\n - Mobiliteit\n stylingAssets:\n configMapRefs:\n - name: includes\n keys:\n - nwb_wegen_hectopunten.symbol\n - hectopunten.style\n - wegvakken.style\n blobKeys:\n - resources/fonts/liberation-sans.ttf\n layers:\n - abstract:\n Deze laag bevat de wegvakken uit het Nationaal Wegen bestand (NWB)\n en geeft gedetailleerde informatie per wegvak zoals straatnaam, wegnummer,\n routenummer, wegbeheerder, huisnummers, enz. weer.\n data:\n gpkg:\n columns:\n - objectid\n - wvk_id\n - wvk_begdat\n - jte_id_beg\n - jte_id_end\n - wegbehsrt\n - wegnummer\n - wegdeelltr\n - hecto_lttr\n - bst_code\n - rpe_code\n - admrichtng\n - rijrichtng\n - stt_naam\n - stt_bron\n - wpsnaam\n - gme_id\n - gme_naam\n - hnrstrlnks\n - hnrstrrhts\n - e_hnr_lnks\n - e_hnr_rhts\n - l_hnr_lnks\n - l_hnr_rhts\n - begafstand\n - endafstand\n - beginkm\n - eindkm\n - pos_tv_wol\n - wegbehcode\n - wegbehnaam\n - distrcode\n - distrnaam\n - dienstcode\n - dienstnaam\n - wegtype\n - wgtype_oms\n - routeltr\n - routenr\n - routeltr2\n - routenr2\n - routeltr3\n - routenr3\n - routeltr4\n - routenr4\n - wegnr_aw\n - wegnr_hmp\n - geobron_id\n - geobron_nm\n - bronjaar\n - openlr\n - bag_orl\n - frc\n - fow\n - alt_naam\n - alt_nr\n - rel_hoogte\n - st_lengthshape\n geometryType: MultiLineString\n blobKey: geopackages/rws/nwbwegen/410a6d1e-e767-41b4-ba8d-9e1e955dd013/1/nwb_wegen.gpkg\n table: wegvakken\n datasetMetadataIdentifier: a9b7026e-0a81-4813-93bd-ba49e6f28502\n keywords:\n - Vervoersnetwerken\n - Menselijke gezondheid en veiligheid\n - Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai)\n - Nationaal\n - Voertuigen\n - Verkeer\n - Wegvakken\n maxScale: 50000.0\n minScale: 1.0\n name: wegvakken\n sourceMetadataIdentifier: 8f0497f0-dbd7-4bee-b85a-5fdec484a7ff\n styles:\n - name: wegvakken\n title: NWB - Wegvakken\n visualization: wegvakken.style\n title: Wegvakken\n visible: true\n - abstract:\n Deze laag bevat de hectopunten uit het Nationaal Wegen Bestand (NWB)\n en geeft gedetailleerde informatie per hectopunt zoals hectometrering, afstand,\n zijde en hectoletter weer.\n data:\n gpkg:\n columns:\n - objectid\n - hectomtrng\n - afstand\n - wvk_id\n - wvk_begdat\n - zijde\n - hecto_lttr\n geometryType: MultiPoint\n blobKey: geopackages/rws/nwbwegen/410a6d1e-e767-41b4-ba8d-9e1e955dd013/1/nwb_wegen.gpkg\n table: hectopunten\n datasetMetadataIdentifier: a9b7026e-0a81-4813-93bd-ba49e6f28502\n keywords:\n - Vervoersnetwerken\n - Menselijke gezondheid en veiligheid\n - Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai)\n - Nationaal\n - Voertuigen\n - Verkeer\n - Hectometerpunten\n maxScale: 50000.0\n minScale: 1.0\n name: hectopunten\n sourceMetadataIdentifier: 8f0497f0-dbd7-4bee-b85a-5fdec484a7ff\n styles:\n - name: hectopunten\n title: NWB - Hectopunten\n visualization: hectopunten.style\n title: Hectopunten\n visible: true\n metadataIdentifier: f2437a92-ddd3-4777-a1bc-fdf4b4a7fcb8\n" var v2wms v2beta1.WMS err := yaml.Unmarshal([]byte(v2wmsstring), &v2wms) @@ -28,7 +28,7 @@ func TestGetConfigMapDataNoLegendFix(t *testing.T) { } func TestGetConfigMapDataLegendFix(t *testing.T) { - + //nolint:misspell v2wmsstring := "apiVersion: pdok.nl/v2beta1\nkind: WMS\nmetadata:\n name: kadaster-kadastralekaart\n labels:\n dataset-owner: kadaster\n dataset: kadastralekaart\n service-version: v5_0\n service-type: wms\nspec:\n general:\n datasetOwner: kadaster\n dataset: kadastralekaart\n serviceVersion: v5_0\n kubernetes:\n healthCheck:\n querystring: language=dut&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX=193882.0336615453998,470528.1693874415942,193922.4213813782844,470564.250484353397&CRS=EPSG:28992&WIDTH=769&HEIGHT=687&LAYERS=OpenbareRuimteNaam,Bebouwing,Perceel,KadastraleGrens&FORMAT=image/png&DPI=96&MAP_RESOLUTION=96&FORMAT_OPTIONS=dpi:96&TRANSPARENT=TRUE\n mimetype: image/png\n resources:\n limits:\n memory: \"100M\"\n ephemeralStorage: \"200M\"\n requests:\n cpu: \"500\"\n memory: \"100M\"\n ephemeralStorage: \"100M\"\n options:\n automaticCasing: true\n disableWebserviceProxy: false\n includeIngress: true\n validateRequests: true\n rewriteGroupToDataLayers: true\n service:\n inspire: false\n title: Kadastrale Kaart (WMS)\n abstract: Overzicht van de ligging van de kadastrale percelen in Nederland. Fungeert als schakel tussen terrein en registratie, vervult voor externe gebruiker vaak een referentiefunctie, een ondergrond ten opzichte waarvan de gebruiker eigen informatie kan vastleggen en presenteren.\n keywords:\n - Kadaster\n - Kadastrale percelen\n - Kadastrale grens\n - Kadastrale kaart\n - Bebouwing\n - Nummeraanduidingreeks\n - Openbare ruimte naam\n - Perceel\n - Grens\n - Kwaliteit\n - Kwaliteitslabels\n - HVD\n - Geospatiale data\n metadataIdentifier: 97cf6a64-9cfc-4ce6-9741-2db44fd27fca\n authority:\n name: kadaster\n url: https://www.kadaster.nl\n dataEPSG: EPSG:28992\n resolution: 91\n defResolution: 91\n extent: \"-25000 250000 280000 860000\"\n maxSize: 10000\n stylingAssets:\n configMapRefs:\n - name: ${INCLUDES}\n blobKeys:\n - ${BLOBS_RESOURCES_BUCKET}/fonts/liberation-sans.ttf\n - ${BLOBS_RESOURCES_BUCKET}/fonts/liberation-sans-italic.ttf\n layers:\n - name: Kadastralekaart\n title: KadastraleKaartv5\n abstract: Overzicht van de ligging van de kadastrale percelen in Nederland. Fungeert als schakel tussen terrein en registratie, vervult voor externe gebruiker vaak een referentiefunctie, een ondergrond ten opzichte waarvan de gebruiker eigen informatie kan vastleggen en presenteren.\n maxScale: 6001\n keywords:\n - Kadaster\n - Kadastrale percelen\n - Kadastrale grens\n datasetMetadataIdentifier: a29917b9-3426-4041-a11b-69bcb2256904\n sourceMetadataIdentifier: 06b6c650-cdb1-11dd-ad8b-0800200c9a64\n styles:\n - name: standaard\n title: Standaardvisualisatie\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n - name: kwaliteit\n title: Kwaliteitsvisualisatie\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n - name: print\n title: Printvisualisatie\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n - name: Bebouwing\n visible: true\n group: Kadastralekaart\n title: Bebouwing\n abstract: De laag Bebouwing is een selectie op panden van de BGT.\n keywords:\n - Bebouwing\n datasetMetadataIdentifier: a29917b9-3426-4041-a11b-69bcb2256904\n sourceMetadataIdentifier: 06b6c650-cdb1-11dd-ad8b-0800200c9a64\n minScale: 50\n maxScale: 6001\n styles:\n - name: standaard:bebouwing\n title: Standaardvisualisatie Bebouwing\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n - name: kwaliteit:bebouwing\n title: Kwaliteitsvisualisatie Bebouwing\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n - name: print:bebouwing\n title: Printvisualisatie Bebouwing\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n - name: Bebouwingvlak\n visible: true\n group: Bebouwing\n title: Bebouwingvlak\n abstract: De laag Bebouwing is een selectie op panden van de BGT.\n keywords:\n - Bebouwing\n datasetMetadataIdentifier: a29917b9-3426-4041-a11b-69bcb2256904\n sourceMetadataIdentifier: 06b6c650-cdb1-11dd-ad8b-0800200c9a64\n minScale: 50\n maxScale: 6001\n styles:\n - name: standaard\n title: Standaardvisualisatie\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n visualization: bebouwing.style\n - name: kwaliteit\n title: Kwaliteitsvisualisatie\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: bebouwing_kwaliteit.style\n - name: print\n title: Printvisualisatie\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: bebouwing_print.style\n - name: standaard:bebouwing\n title: Standaardvisualisatie Bebouwing\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n visualization: bebouwing.group.style\n - name: kwaliteit:bebouwing\n title: Kwaliteitsvisualisatie Bebouwing\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: bebouwing_kwaliteit.group.style\n - name: print:bebouwing\n title: Printvisualisatie Bebouwing\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: bebouwing_print.group.style\n data:\n gpkg:\n blobKey: ${BLOBS_GEOPACKAGES_BUCKET}/kadaster/kadastralekaart_brk/${GPKG_VERSION}/pand.gpkg\n table: pand\n geometryType: Polygon\n columns:\n - object_begin_tijd\n - lv_publicatiedatum\n - relatieve_hoogteligging\n - in_onderzoek\n - tijdstip_registratie\n - identificatie_namespace\n - identificatie_lokaal_id\n - bronhouder\n - bgt_status\n - plus_status\n - identificatie_bag_pnd\n aliases:\n lv_publicatiedatum: LV-publicatiedatum\n identificatie_lokaal_id: identificatieLokaalID\n identificatie_bag_pnd: identificatieBAGPND\n bgt_status: bgt-status\n plus_status: plus-status\n - name: Nummeraanduidingreeks\n visible: true\n group: Bebouwing\n title: Nummeraanduidingreeks\n abstract: De laag Bebouwing is een selectie op panden van de BGT.\n keywords:\n - Nummeraanduidingreeks\n datasetMetadataIdentifier: a29917b9-3426-4041-a11b-69bcb2256904\n sourceMetadataIdentifier: 06b6c650-cdb1-11dd-ad8b-0800200c9a64\n minScale: 50\n maxScale: 2001\n styles:\n - name: standaard\n title: Standaardvisualisatie\n abstract: Standaarvisualisatie van de nummeraanduidingreeks.\n visualization: nummeraanduidingreeks.style\n - name: kwaliteit\n title: Kwaliteitsvisualisatie\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: nummeraanduidingreeks_kwaliteit.style\n - name: print\n title: Printvisualisatie\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: nummeraanduidingreeks_print.style\n - name: standaard:bebouwing\n title: Standaardvisualisatie Bebouwing\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n visualization: nummeraanduidingreeks.group.style\n - name: kwaliteit:bebouwing\n title: Kwaliteitsvisualisatie Bebouwing\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: nummeraanduidingreeks_kwaliteit.group.style\n - name: print:bebouwing\n title: Printvisualisatie Bebouwing\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: nummeraanduidingreeks_print.group.style\n data:\n gpkg:\n blobKey: ${BLOBS_GEOPACKAGES_BUCKET}/kadaster/kadastralekaart_brk/${GPKG_VERSION}/pand_nummeraanduiding.gpkg\n table: pand_nummeraanduiding\n geometryType: Point\n columns:\n - bebouwing_id\n - hoek\n - tekst\n - bag_vbo_laagste_huisnummer\n - bag_vbo_hoogste_huisnummer\n - hoek\n aliases:\n bebouwing_id: bebouwingID\n bag_vbo_laagste_huisnummer: identificatie_BAGVBOLaagsteHuisnummer\n bag_vbo_hoogste_huisnummer: identificatie_BAGVBOHoogsteHuisnummer\n - name: OpenbareRuimteNaam\n visible: true\n group: Kadastralekaart\n title: OpenbareRuimteNaam\n abstract: De laag Openbareruimtenaam is een selectie op de openbare ruimte labels van de BGT met een bgt-status \"bestaand\" die een classificatie (openbareruimtetype) Weg en Water hebben.\n keywords:\n - Openbare ruimte naam\n datasetMetadataIdentifier: a29917b9-3426-4041-a11b-69bcb2256904\n sourceMetadataIdentifier: 06b6c650-cdb1-11dd-ad8b-0800200c9a64\n minScale: 50\n maxScale: 2001\n styles:\n - name: standaard\n title: Standaardvisualisatie\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n visualization: openbareruimtenaam.style\n - name: kwaliteit\n title: Kwaliteitsvisualisatie\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: openbareruimtenaam_kwaliteit.style\n - name: print\n title: Printvisualisatie\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: openbareruimtenaam_print.style\n - name: standaard:openbareruimtenaam\n title: Standaardvisualisatie OpenbareRuimteNaam\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n visualization: openbareruimtenaam.group.style\n - name: kwaliteit:openbareruimtenaam\n title: Kwaliteitsvisualisatie OpenbareRuimteNaam\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: openbareruimtenaam_kwaliteit.group.style\n - name: print:openbareruimtenaam\n title: Printvisualisatie OpenbareRuimteNaam\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: openbareruimtenaam_print.group.style\n data:\n gpkg:\n blobKey: ${BLOBS_GEOPACKAGES_BUCKET}/kadaster/kadastralekaart_brk/${GPKG_VERSION}/openbareruimtelabel.gpkg\n table: openbareruimtelabel\n geometryType: Point\n columns:\n - object_begin_tijd\n - lv_publicatiedatum\n - relatieve_hoogteligging\n - in_onderzoek\n - tijdstip_registratie\n - identificatie_namespace\n - identificatie_lokaal_id\n - bronhouder\n - bgt_status\n - plus_status\n - identificatie_bag_opr\n - tekst\n - hoek\n - openbare_ruimte_type\n aliases:\n lv_publicatiedatum: LV-publicatiedatum\n identificatie_lokaal_id: identificatieLokaalID\n identificatie_bag_opr: identificatieBAGOPR\n bgt_status: bgt-status\n plus_status: plus-status\n - name: Perceel\n visible: true\n group: Kadastralekaart\n title: Perceel\n abstract: Een perceel is een stuk grond waarvan het Kadaster de grenzen heeft gemeten of gaat meten en dat bij het Kadaster een eigen nummer heeft. Een perceel is een begrensd deel van het Nederlands grondgebied dat kadastraal geïdentificeerd is en met kadastrale grenzen begrensd is.\n keywords:\n - Perceel\n - Kadastrale percelen\n datasetMetadataIdentifier: a29917b9-3426-4041-a11b-69bcb2256904\n sourceMetadataIdentifier: 06b6c650-cdb1-11dd-ad8b-0800200c9a64\n minScale: 50\n maxScale: 6001\n styles:\n - name: standaard:perceel\n title: Standaardvisualisatie Perceel\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n - name: kwaliteit:perceel\n title: Kwaliteitsvisualisatie Perceel\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n - name: print:perceel\n title: Printvisualisatie Perceel\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n - name: Perceelvlak\n visible: true\n group: Perceel\n title: Perceelvlak\n abstract: Een perceel is een stuk grond waarvan het Kadaster de grenzen heeft gemeten of gaat meten en dat bij het Kadaster een eigen nummer heeft. Een perceel is een begrensd deel van het Nederlands grondgebied dat kadastraal geïdentificeerd is en met kadastrale grenzen begrensd is.\n keywords:\n - Kadastrale percelen\n datasetMetadataIdentifier: a29917b9-3426-4041-a11b-69bcb2256904\n sourceMetadataIdentifier: 06b6c650-cdb1-11dd-ad8b-0800200c9a64\n minScale: 50\n maxScale: 6001\n styles:\n - name: standaard\n title: Standaardvisualisatie\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n visualization: perceelvlak.style\n - name: kwaliteit\n title: Kwaliteitsvisualisatie\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: perceelvlak_kwaliteit.style\n - name: print\n title: Printvisualisatie\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: perceelvlak_print.style\n - name: standaard:perceel\n title: Standaardvisualisatie Perceel\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n visualization: perceelvlak.group.style\n - name: kwaliteit:perceel\n title: Kwaliteitsvisualisatie Perceel\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: perceelvlak_kwaliteit.group.style\n - name: print:perceel\n title: Printvisualisatie Perceel\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: perceelvlak_print.group.style\n data:\n gpkg:\n blobKey: ${BLOBS_GEOPACKAGES_BUCKET}/kadaster/kadastralekaart_brk/${GPKG_VERSION}/perceel.gpkg\n table: perceel\n geometryType: Polygon\n columns:\n - identificatie_namespace\n - identificatie_lokaal_id\n - begin_geldigheid\n - tijdstip_registratie\n - volgnummer\n - status_historie_code\n - status_historie_waarde\n - kadastrale_gemeente_code\n - kadastrale_gemeente_waarde\n - sectie\n - akr_kadastrale_gemeente_code_code\n - akr_kadastrale_gemeente_code_waarde\n - kadastrale_grootte_waarde\n - soort_grootte_code\n - soort_grootte_waarde\n - perceelnummer\n - perceelnummer_rotatie\n - perceelnummer_verschuiving_delta_x\n - perceelnummer_verschuiving_delta_y\n - perceelnummer_plaatscoordinaat_x\n - perceelnummer_plaatscoordinaat_y\n aliases:\n identificatie_lokaal_id: identificatieLokaalID\n akr_kadastrale_gemeente_code_code: AKRKadastraleGemeenteCodeCode\n akr_kadastrale_gemeente_code_waarde: AKRKadastraleGemeenteCodeWaarde\n - name: Label\n visible: true\n group: Perceel\n title: Label\n abstract: Een perceel is een stuk grond waarvan het Kadaster de grenzen heeft gemeten of gaat meten en dat bij het Kadaster een eigen nummer heeft. Een perceel is een begrensd deel van het Nederlands grondgebied dat kadastraal geïdentificeerd is en met kadastrale grenzen begrensd is.\n keywords:\n - Kadastrale percelen\n datasetMetadataIdentifier: a29917b9-3426-4041-a11b-69bcb2256904\n sourceMetadataIdentifier: 06b6c650-cdb1-11dd-ad8b-0800200c9a64\n minScale: 50\n maxScale: 6001\n styles:\n - name: standaard\n title: Standaardvisualisatie\n abstract: Standaarvisualisatie van het label.\n visualization: label.style\n - name: standaard:perceel\n title: Standaardvisualisatie Perceel\n abstract: Standaarvisualisatie van het label.\n visualization: label.group.style\n - name: kwaliteit\n title: Kwaliteitsvisualisatie\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: label_kwaliteit.style\n - name: kwaliteit:perceel\n title: Kwaliteitsvisualisatie Perceel\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: label_kwaliteit.group.style\n - name: print\n title: Printvisualisatie\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: label_print.style\n - name: print:perceel\n title: Printvisualisatie Perceel\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: label_print.group.style\n data:\n gpkg:\n blobKey: ${BLOBS_GEOPACKAGES_BUCKET}/kadaster/kadastralekaart_brk/${GPKG_VERSION}/perceel_label.gpkg\n table: perceel_label\n geometryType: Point\n columns:\n - perceel_id\n - perceelnummer\n - rotatie\n - verschuiving_delta_x\n - verschuiving_delta_y\n aliases:\n perceel_id: perceelID\n - name: Bijpijling\n visible: true\n group: Perceel\n title: Bijpijling\n abstract: Een perceel is een stuk grond waarvan het Kadaster de grenzen heeft gemeten of gaat meten en dat bij het Kadaster een eigen nummer heeft. Een perceel is een begrensd deel van het Nederlands grondgebied dat kadastraal geïdentificeerd is en met kadastrale grenzen begrensd is.\n keywords:\n - Kadastrale percelen\n datasetMetadataIdentifier: a29917b9-3426-4041-a11b-69bcb2256904\n sourceMetadataIdentifier: 06b6c650-cdb1-11dd-ad8b-0800200c9a64\n minScale: 50\n maxScale: 6001\n styles:\n - name: standaard\n title: Standaardvisualisatie\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n visualization: bijpijling.style\n - name: kwaliteit\n title: Kwaliteitsvisualisatie\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: bijpijling_kwaliteit.style\n - name: print\n title: Printvisualisatie\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: bijpijling_print.style\n - name: standaard:perceel\n title: Standaardvisualisatie Perceel\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n visualization: bijpijling.group.style\n - name: kwaliteit:perceel\n title: Kwaliteitsvisualisatie Perceel\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: bijpijling_kwaliteit.group.style\n - name: print:perceel\n title: Printvisualisatie Perceel\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: bijpijling_print.group.style\n data:\n gpkg:\n blobKey: ${BLOBS_GEOPACKAGES_BUCKET}/kadaster/kadastralekaart_brk/${GPKG_VERSION}/perceel_bijpijling.gpkg\n table: perceel_bijpijling\n geometryType: LineString\n columns:\n - perceel_id\n aliases:\n perceel_id: perceelID\n - name: KadastraleGrens\n visible: true\n group: Kadastralekaart\n title: KadastraleGrens\n abstract: Een Kadastrale Grens is de weergave van een grens op de kadastrale kaart die door de dienst van het Kadaster tussen percelen (voorlopig) vastgesteld wordt, op basis van inlichtingen van belanghebbenden en met gebruikmaking van de aan de kadastrale kaart ten grondslag liggende bescheiden die in elk geval de landmeetkundige gegevens bevatten van hetgeen op die kaart wordt weergegeven.\n keywords:\n - Grens\n - Kadastrale grenzen\n datasetMetadataIdentifier: a29917b9-3426-4041-a11b-69bcb2256904\n sourceMetadataIdentifier: 06b6c650-cdb1-11dd-ad8b-0800200c9a64\n minScale: 50\n maxScale: 6001\n styles:\n - name: standaard\n title: Standaardvisualisatie\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n visualization: kadastralegrens.style\n - name: kwaliteit\n title: Kwaliteitsvisualisatie\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: kadastralegrens_kwaliteit.style\n - name: print\n title: Printvisualisatie\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: kadastralegrens_print.style\n - name: standaard:kadastralegrens\n title: Standaardvisualisatie KadastraleGrens\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n visualization: kadastralegrens.group.style\n - name: kwaliteit:kadastralegrens\n title: Kwaliteitsvisualisatie KadastraleGrens\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: kadastralegrens_kwaliteit.group.style\n - name: print:kadastralegrens\n title: Printvisualisatie KadastraleGrens\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: kadastralegrens_print.group.style\n data:\n gpkg:\n blobKey: ${BLOBS_GEOPACKAGES_BUCKET}/kadaster/kadastralekaart_brk/${GPKG_VERSION}/kadastrale_grens.gpkg\n table: kadastrale_grens\n geometryType: LineString\n columns:\n - begin_geldigheid\n - tijdstip_registratie\n - volgnummer\n - status_historie_code\n - status_historie_waarde\n - identificatie_namespace\n - identificatie_lokaal_id\n - type_grens_code\n - type_grens_waarde\n - classificatie_kwaliteit_code\n - classificatie_kwaliteit_waarde\n - perceel_links_identificatie_namespace\n - perceel_links_identificatie_lokaal_id\n - perceel_rechts_identificatie_namespace\n - perceel_rechts_identificatie_lokaal_id\n aliases:\n identificatie_lokaal_id: identificatieLokaalID\n perceel_links_identificatie_lokaal_id: perceelLinksIdentificatieLokaalID\n perceel_rechts_identificatie_lokaal_id: perceelRechtsIdentificatieLokaalID\n classificatie_kwaliteit_code: ClassificatieKwaliteitCode\n classificatie_kwaliteit_waarde: ClassificatieKwaliteitWaarde\n" var v2wms v2beta1.WMS err := yaml.Unmarshal([]byte(v2wmsstring), &v2wms) diff --git a/internal/controller/mapfilegenerator/mapfile_generator_test.go b/internal/controller/mapfilegenerator/mapfile_generator_test.go index 62ecf42..ea1be94 100644 --- a/internal/controller/mapfilegenerator/mapfile_generator_test.go +++ b/internal/controller/mapfilegenerator/mapfile_generator_test.go @@ -29,6 +29,7 @@ const ( "service_metadata_id": "metameta-meta-meta-meta-metametameta", "automatic_casing": true, "data_epsg": "EPSG:28992", + "service_debug_level": 0, "epsg_list": [ "EPSG:28992", "EPSG:25831", @@ -87,8 +88,11 @@ const ( } ] }` - WMSGrouplessConfig = `{"service_title": "NWB - Wegen WMS", "service_abstract": "Dit is de web map service van het Nationaal Wegen Bestand (NWB) - wegen. Deze dataset bevat alleen de wegvakken en hectometerpunten. Het Nationaal Wegen Bestand - Wegen is een digitaal geografisch bestand van alle wegen in Nederland. Opgenomen zijn alle wegen die worden beheerd door wegbeheerders als het Rijk, provincies, gemeenten en waterschappen, echter alleen voor zover deze zijn voorzien van een straatnaam of nummer.", "service_keywords": "Vervoersnetwerken,Menselijke gezondheid en veiligheid,Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai),Nationaal,Voertuigen,Verkeer,Wegvakken,Hectometerpunten,HVD,Mobiliteit", "service_accessconstraints": "https://creativecommons.org/publicdomain/zero/1.0/deed.nl", "service_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "maxSize": "4000", "service_namespace_prefix": "nwbwegen", "service_namespace_uri": "http://nwbwegen.geonovum.nl", "service_onlineresource": "https://service.pdok.nl", "service_path": "/rws/nwbwegen/wms/v1_0", "service_metadata_id": "f2437a92-ddd3-4777-a1bc-fdf4b4a7fcb8", "dataset_owner": "rws", "authority_url": "https://www.rijkswaterstaat.nl", "automatic_casing": true, "data_epsg": "EPSG:28992", "epsg_list": ["EPSG:28992", "EPSG:25831", "EPSG:25832", "EPSG:3034", "EPSG:3035", "EPSG:3857", "EPSG:4258", "EPSG:4326", "CRS:84"], "templates": "/srv/data/config/templates", "fonts": "/srv/data/config/fonts", "outputformat_jpg": "jpg", "outputformat_png8": "png", "symbols": ["/styling/nwb_wegen_hectopunten.symbol"], "group_layers": [], "layers": [{"name": "wegvakken", "gpkg_path": "/srv/data/gpkg/nwb_wegen.gpkg", "tablename": "wegvakken", "geometry_type": "MultiLineString", "columns": [{"name": "fuuid"}, {"name": "objectid"}, {"name": "wvk_id"}, {"name": "wvk_begdat"}, {"name": "jte_id_beg"}, {"name": "jte_id_end"}, {"name": "wegbehsrt"}, {"name": "wegnummer"}, {"name": "wegdeelltr"}, {"name": "hecto_lttr"}, {"name": "bst_code"}, {"name": "rpe_code"}, {"name": "admrichtng"}, {"name": "rijrichtng"}, {"name": "stt_naam"}, {"name": "stt_bron"}, {"name": "wpsnaam"}, {"name": "gme_id"}, {"name": "gme_naam"}, {"name": "hnrstrlnks"}, {"name": "hnrstrrhts"}, {"name": "e_hnr_lnks"}, {"name": "e_hnr_rhts"}, {"name": "l_hnr_lnks"}, {"name": "l_hnr_rhts"}, {"name": "begafstand"}, {"name": "endafstand"}, {"name": "beginkm"}, {"name": "eindkm"}, {"name": "pos_tv_wol"}, {"name": "wegbehcode"}, {"name": "wegbehnaam"}, {"name": "distrcode"}, {"name": "distrnaam"}, {"name": "dienstcode"}, {"name": "dienstnaam"}, {"name": "wegtype"}, {"name": "wgtype_oms"}, {"name": "routeltr"}, {"name": "routenr"}, {"name": "routeltr2"}, {"name": "routenr2"}, {"name": "routeltr3"}, {"name": "routenr3"}, {"name": "routeltr4"}, {"name": "routenr4"}, {"name": "wegnr_aw"}, {"name": "wegnr_hmp"}, {"name": "geobron_id"}, {"name": "geobron_nm"}, {"name": "bronjaar"}, {"name": "openlr"}, {"name": "bag_orl"}, {"name": "frc"}, {"name": "fow"}, {"name": "alt_naam"}, {"name": "alt_nr"}, {"name": "rel_hoogte"}, {"name": "st_lengthshape"}], "title": "Wegvakken", "abstract": "Deze laag bevat de wegvakken uit het Nationaal Wegen bestand (NWB) en geeft gedetailleerde informatie per wegvak zoals straatnaam, wegnummer, routenummer, wegbeheerder, huisnummers, enz. weer.", "keywords": "Vervoersnetwerken,Menselijke gezondheid en veiligheid,Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai),Nationaal,Voertuigen,Verkeer,Wegvakken", "dataset_metadata_id": "a9b7026e-0a81-4813-93bd-ba49e6f28502", "dataset_source_id": "8f0497f0-dbd7-4bee-b85a-5fdec484a7ff", "layer_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "minscale": "1", "maxscale": "50000", "styles": [{"title": "NWB - Wegvakken", "path": "/styling/wegvakken.style"}]}, {"name": "hectopunten", "gpkg_path": "/srv/data/gpkg/nwb_wegen.gpkg", "tablename": "hectopunten", "geometry_type": "MultiPoint", "columns": [{"name": "fuuid"}, {"name": "objectid"}, {"name": "hectomtrng"}, {"name": "afstand"}, {"name": "wvk_id"}, {"name": "wvk_begdat"}, {"name": "zijde"}, {"name": "hecto_lttr"}], "title": "Hectopunten", "abstract": "Deze laag bevat de hectopunten uit het Nationaal Wegen Bestand (NWB) en geeft gedetailleerde informatie per hectopunt zoals hectometrering, afstand, zijde en hectoletter weer.", "keywords": "Vervoersnetwerken,Menselijke gezondheid en veiligheid,Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai),Nationaal,Voertuigen,Verkeer,Hectometerpunten", "dataset_metadata_id": "a9b7026e-0a81-4813-93bd-ba49e6f28502", "dataset_source_id": "8f0497f0-dbd7-4bee-b85a-5fdec484a7ff", "layer_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "minscale": "1", "maxscale": "50000", "styles": [{"title": "NWB - Hectopunten", "path": "/styling/hectopunten.style"}]}]}` - WMSGroupConfig = `{"service_title": "Waterschappen Hydrografie (INSPIRE geharmoniseerd) WMS", "service_abstract": "Deze dataset is gebaseerd op (niet geharmoniseerde) data van alle waterschappen in Nederland conform INSPIRE. De dataset bevat de volgende INSPIRE objecten: CrossingLine, CrossingPoint, DamOrWeir, DrainageBasin, Embankment, Lock, Sluice, Watercourse.", "service_keywords": "Aquaduct,Brug,Duikersifonhevel,Stuw,Vastedam,AfvoerAanvoergebied,Waterkering,Sluis,HydroObject,HVD,Aardobservatie en milieu", "service_accessconstraints": "https://creativecommons.org/publicdomain/zero/1.0/deed.nl", "service_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "maxSize": "4000", "service_namespace_prefix": "hydrografie", "service_namespace_uri": "http://hydrografie.geonovum.nl", "service_onlineresource": "https://service.pdok.nl", "service_path": "/hwh/hydrografie/wms/v2_0", "service_metadata_id": "871a58f8-c9f1-41a4-be37-0f059e0f886f", "dataset_owner": "hwh", "authority_url": "https://www.hetwaterschapshuis.nl/", "automatic_casing": false, "data_epsg": "EPSG:28992", "epsg_list": ["EPSG:28992", "EPSG:25831", "EPSG:25832", "EPSG:3034", "EPSG:3035", "EPSG:3857", "EPSG:4258", "EPSG:4326", "CRS:84"], "templates": "/srv/data/config/templates", "outputformat_jpg": "jpg", "outputformat_png8": "png", "symbols": ["/styling/bridge.symbol", "/styling/x.symbol"], "group_layers": [{"name": "HY.PhysicalWaters.ManMadeObject", "title": "Man-made Object", "abstract": "Crossing line, crossing point, dam or weir, sluice, embankment, lock.", "style_name": "HY.PhysicalWaters.ManMadeObject.Default", "style_title": "Man-made objects default style"}], "layers": [{"name": "HY.PhysicalWaters.Waterbodies", "gpkg_path": "/srv/data/gpkg/Waterbody.gpkg", "tablename": "watercourse", "geometry_type": "MultiLineString", "columns": [{"name": "fuuid"}, {"name": "gml_id"}, {"name": "beginlifespanversion"}, {"name": "condition"}, {"name": "delineationknown"}, {"name": "endlifespanversion"}, {"name": "length"}, {"name": "level"}, {"name": "localid"}, {"name": "localtype"}, {"name": "name"}, {"name": "namespace"}, {"name": "origin"}, {"name": "persistence"}, {"name": "streamorder"}, {"name": "tidal"}, {"name": "widthrange"}], "title": "Waterbody", "abstract": "Watercourse", "keywords": "Hydroobject,Waterbody,Watercourse,River,Stream,Lake,Reservoir", "dataset_metadata_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "dataset_source_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "layer_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "minscale": "1", "maxscale": "50000", "styles": [{"title": "Water bodies default style", "path": "/styling/watercourse.style"}]}, {"name": "HY.PhysicalWaters.Catchments", "gpkg_path": "/srv/data/gpkg/Catchment.gpkg", "tablename": "drainagebasin", "geometry_type": "MultiPolygon", "columns": [{"name": "fuuid"}, {"name": "gml_id"}, {"name": "area"}, {"name": "beginlifespanversion"}, {"name": "endlifespanversion"}, {"name": "localid"}, {"name": "name"}, {"name": "namespace"}, {"name": "order"}, {"name": "orderscheme"}, {"name": "origin"}, {"name": "outlet"}, {"name": "scope"}], "title": "Catchment", "abstract": "Drainage basin", "keywords": "AfvoergebiedAanvoergebied,Catchment,Basin,Catchment Area,Drainage basin", "dataset_metadata_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "dataset_source_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "layer_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "minscale": "1", "maxscale": "50000", "styles": [{"title": "Drainage Basin default style", "path": "/styling/drainagebasin.style"}]}, {"name": "HY.PhysicalWaters.ManMadeObject.lock", "group_name": "HY.PhysicalWaters.ManMadeObject", "gpkg_path": "/srv/data/gpkg/Man-madeObject.gpkg", "tablename": "lock", "geometry_type": "Point", "columns": [{"name": "fuuid"}, {"name": "gml_id"}, {"name": "beginlifespanversion"}, {"name": "condition"}, {"name": "endlifespanversion"}, {"name": "localid"}, {"name": "name"}, {"name": "namespace"}], "title": "Man-made Object", "abstract": "Crossing line, crossing point, dam or weir, sluice, embankment, lock.", "keywords": "Man Made,Duikersifonhevel,Aquaduct,Brug,Stuw,Vastedam,Waterkering,Sluis.", "dataset_metadata_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "dataset_source_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "layer_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "minscale": "1", "maxscale": "50000", "styles": [{"title": "Lock", "path": "/styling/lock.style"}]}, {"name": "HY.PhysicalWaters.ManMadeObject.crossingpoint", "group_name": "HY.PhysicalWaters.ManMadeObject", "gpkg_path": "/srv/data/gpkg/Man-madeObject.gpkg", "tablename": "crossingpoint", "geometry_type": "Point", "columns": [{"name": "fuuid"}, {"name": "gml_id"}, {"name": "beginlifespanversion"}, {"name": "condition"}, {"name": "endlifespanversion"}, {"name": "localid"}, {"name": "name"}, {"name": "namespace"}, {"name": "type"}], "title": "Man-made Object", "abstract": "Crossing line, crossing point, dam or weir, sluice, embankment, lock.", "keywords": "Man Made,Duikersifonhevel,Aquaduct,Brug,Stuw,Vastedam,Waterkering,Sluis.", "dataset_metadata_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "dataset_source_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "layer_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "minscale": "1", "maxscale": "50000", "styles": [{"title": "Crossing Point", "path": "/styling/crossingpoint.style"}]}, {"name": "HY.PhysicalWaters.ManMadeObject.sluice", "group_name": "HY.PhysicalWaters.ManMadeObject", "gpkg_path": "/srv/data/gpkg/Man-madeObject.gpkg", "tablename": "sluice", "geometry_type": "Point", "columns": [{"name": "fuuid"}, {"name": "gml_id"}, {"name": "beginlifespanversion"}, {"name": "condition"}, {"name": "endlifespanversion"}, {"name": "localid"}, {"name": "name"}, {"name": "namespace"}], "title": "Man-made Object", "abstract": "Crossing line, crossing point, dam or weir, sluice, embankment, lock.", "keywords": "Man Made,Duikersifonhevel,Aquaduct,Brug,Stuw,Vastedam,Waterkering,Sluis.", "dataset_metadata_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "dataset_source_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "layer_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "minscale": "1", "maxscale": "50000", "styles": [{"title": "Sluice", "path": "/styling/sluice.style"}]}, {"name": "HY.PhysicalWaters.ManMadeObject.embankment", "group_name": "HY.PhysicalWaters.ManMadeObject", "gpkg_path": "/srv/data/gpkg/Man-madeObject.gpkg", "tablename": "embankment", "geometry_type": "MultiLineString", "columns": [{"name": "fuuid"}, {"name": "gml_id"}, {"name": "beginlifespanversion"}, {"name": "condition"}, {"name": "endlifespanversion"}, {"name": "localid"}, {"name": "name"}, {"name": "namespace"}], "title": "Man-made Object", "abstract": "Crossing line, crossing point, dam or weir, sluice, embankment, lock.", "keywords": "Man Made,Duikersifonhevel,Aquaduct,Brug,Stuw,Vastedam,Waterkering,Sluis.", "dataset_metadata_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "dataset_source_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "layer_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "minscale": "1", "maxscale": "50000", "styles": [{"title": "Embankment", "path": "/styling/embankment.style"}]}, {"name": "HY.PhysicalWaters.ManMadeObject.crossingline", "group_name": "HY.PhysicalWaters.ManMadeObject", "gpkg_path": "/srv/data/gpkg/Man-madeObject.gpkg", "tablename": "crossingline", "geometry_type": "MultiLineString", "columns": [{"name": "fuuid"}, {"name": "gml_id"}, {"name": "beginlifespanversion"}, {"name": "condition"}, {"name": "endlifespanversion"}, {"name": "localid"}, {"name": "name"}, {"name": "namespace"}, {"name": "type"}], "title": "Man-made Object", "abstract": "Crossing line, crossing point, dam or weir, sluice, embankment, lock.", "keywords": "Man Made,Duikersifonhevel,Aquaduct,Brug,Stuw,Vastedam,Waterkering,Sluis.", "dataset_metadata_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "dataset_source_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "layer_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "minscale": "1", "maxscale": "50000", "styles": [{"title": "Crossing Line", "path": "/styling/crossingline.style"}]}, {"name": "HY.PhysicalWaters.ManMadeObject.damorweir", "group_name": "HY.PhysicalWaters.ManMadeObject", "gpkg_path": "/srv/data/gpkg/Man-madeObject.gpkg", "tablename": "damorweir", "geometry_type": "Point", "columns": [{"name": "fuuid"}, {"name": "gml_id"}, {"name": "beginlifespanversion"}, {"name": "condition"}, {"name": "endlifespanversion"}, {"name": "localid"}, {"name": "name"}, {"name": "namespace"}], "title": "Man-made Object", "abstract": "Crossing line, crossing point, dam or weir, sluice, embankment, lock.", "keywords": "Man Made,Duikersifonhevel,Aquaduct,Brug,Stuw,Vastedam,Waterkering,Sluis.", "dataset_metadata_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "dataset_source_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "layer_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "minscale": "1", "maxscale": "50000", "styles": [{"title": "Dam or Weir", "path": "/styling/damorweir.style"}]}]}` + //nolint:misspell + WMSGrouplessConfig = `{"service_title": "NWB - Wegen WMS", "service_abstract": "Dit is de web map service van het Nationaal Wegen Bestand (NWB) - wegen. Deze dataset bevat alleen de wegvakken en hectometerpunten. Het Nationaal Wegen Bestand - Wegen is een digitaal geografisch bestand van alle wegen in Nederland. Opgenomen zijn alle wegen die worden beheerd door wegbeheerders als het Rijk, provincies, gemeenten en waterschappen, echter alleen voor zover deze zijn voorzien van een straatnaam of nummer.", "service_keywords": "Vervoersnetwerken,Menselijke gezondheid en veiligheid,Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai),Nationaal,Voertuigen,Verkeer,Wegvakken,Hectometerpunten,HVD,Mobiliteit", "service_accessconstraints": "https://creativecommons.org/publicdomain/zero/1.0/deed.nl", "service_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "maxSize": "4000", "service_namespace_prefix": "nwbwegen", "service_namespace_uri": "http://nwbwegen.geonovum.nl", "service_onlineresource": "https://service.pdok.nl", "service_path": "/rws/nwbwegen/wms/v1_0", "service_metadata_id": "f2437a92-ddd3-4777-a1bc-fdf4b4a7fcb8", "dataset_owner": "rws", "authority_url": "https://www.rijkswaterstaat.nl", "automatic_casing": true, "data_epsg": "EPSG:28992", "epsg_list": ["EPSG:28992", "EPSG:25831", "EPSG:25832", "EPSG:3034", "EPSG:3035", "EPSG:3857", "EPSG:4258", "EPSG:4326", "CRS:84"], "templates": "/srv/data/config/templates", "fonts": "/srv/data/config/fonts", "outputformat_jpg": "jpg", "outputformat_png8": "png", "symbols": ["/styling/nwb_wegen_hectopunten.symbol"], "group_layers": [], "layers": [{"name": "wegvakken", "gpkg_path": "/srv/data/gpkg/nwb_wegen.gpkg", "tablename": "wegvakken", "geometry_type": "MultiLineString", "columns": [{"name": "fuuid"}, {"name": "objectid"}, {"name": "wvk_id"}, {"name": "wvk_begdat"}, {"name": "jte_id_beg"}, {"name": "jte_id_end"}, {"name": "wegbehsrt"}, {"name": "wegnummer"}, {"name": "wegdeelltr"}, {"name": "hecto_lttr"}, {"name": "bst_code"}, {"name": "rpe_code"}, {"name": "admrichtng"}, {"name": "rijrichtng"}, {"name": "stt_naam"}, {"name": "stt_bron"}, {"name": "wpsnaam"}, {"name": "gme_id"}, {"name": "gme_naam"}, {"name": "hnrstrlnks"}, {"name": "hnrstrrhts"}, {"name": "e_hnr_lnks"}, {"name": "e_hnr_rhts"}, {"name": "l_hnr_lnks"}, {"name": "l_hnr_rhts"}, {"name": "begafstand"}, {"name": "endafstand"}, {"name": "beginkm"}, {"name": "eindkm"}, {"name": "pos_tv_wol"}, {"name": "wegbehcode"}, {"name": "wegbehnaam"}, {"name": "distrcode"}, {"name": "distrnaam"}, {"name": "dienstcode"}, {"name": "dienstnaam"}, {"name": "wegtype"}, {"name": "wgtype_oms"}, {"name": "routeltr"}, {"name": "routenr"}, {"name": "routeltr2"}, {"name": "routenr2"}, {"name": "routeltr3"}, {"name": "routenr3"}, {"name": "routeltr4"}, {"name": "routenr4"}, {"name": "wegnr_aw"}, {"name": "wegnr_hmp"}, {"name": "geobron_id"}, {"name": "geobron_nm"}, {"name": "bronjaar"}, {"name": "openlr"}, {"name": "bag_orl"}, {"name": "frc"}, {"name": "fow"}, {"name": "alt_naam"}, {"name": "alt_nr"}, {"name": "rel_hoogte"}, {"name": "st_lengthshape"}], "title": "Wegvakken", "abstract": "Deze laag bevat de wegvakken uit het Nationaal Wegen bestand (NWB) en geeft gedetailleerde informatie per wegvak zoals straatnaam, wegnummer, routenummer, wegbeheerder, huisnummers, enz. weer.", "keywords": "Vervoersnetwerken,Menselijke gezondheid en veiligheid,Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai),Nationaal,Voertuigen,Verkeer,Wegvakken", "dataset_metadata_id": "a9b7026e-0a81-4813-93bd-ba49e6f28502", "dataset_source_id": "8f0497f0-dbd7-4bee-b85a-5fdec484a7ff", "layer_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "minscale": "1", "maxscale": "50000", "styles": [{"title": "NWB - Wegvakken", "path": "/styling/wegvakken.style"}]}, {"name": "hectopunten", "gpkg_path": "/srv/data/gpkg/nwb_wegen.gpkg", "tablename": "hectopunten", "geometry_type": "MultiPoint", "columns": [{"name": "fuuid"}, {"name": "objectid"}, {"name": "hectomtrng"}, {"name": "afstand"}, {"name": "wvk_id"}, {"name": "wvk_begdat"}, {"name": "zijde"}, {"name": "hecto_lttr"}], "title": "Hectopunten", "abstract": "Deze laag bevat de hectopunten uit het Nationaal Wegen Bestand (NWB) en geeft gedetailleerde informatie per hectopunt zoals hectometrering, afstand, zijde en hectoletter weer.", "keywords": "Vervoersnetwerken,Menselijke gezondheid en veiligheid,Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai),Nationaal,Voertuigen,Verkeer,Hectometerpunten", "dataset_metadata_id": "a9b7026e-0a81-4813-93bd-ba49e6f28502", "dataset_source_id": "8f0497f0-dbd7-4bee-b85a-5fdec484a7ff", "layer_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "minscale": "1", "maxscale": "50000", "styles": [{"title": "NWB - Hectopunten", "path": "/styling/hectopunten.style"}]}]}` + //nolint:misspell + WMSGroupConfig = `{"service_title": "Waterschappen Hydrografie (INSPIRE geharmoniseerd) WMS", "service_abstract": "Deze dataset is gebaseerd op (niet geharmoniseerde) data van alle waterschappen in Nederland conform INSPIRE. De dataset bevat de volgende INSPIRE objecten: CrossingLine, CrossingPoint, DamOrWeir, DrainageBasin, Embankment, Lock, Sluice, Watercourse.", "service_keywords": "Aquaduct,Brug,Duikersifonhevel,Stuw,Vastedam,AfvoerAanvoergebied,Waterkering,Sluis,HydroObject,HVD,Aardobservatie en milieu", "service_accessconstraints": "https://creativecommons.org/publicdomain/zero/1.0/deed.nl", "service_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "maxSize": "4000", "service_namespace_prefix": "hydrografie", "service_namespace_uri": "http://hydrografie.geonovum.nl", "service_onlineresource": "https://service.pdok.nl", "service_path": "/hwh/hydrografie/wms/v2_0", "service_metadata_id": "871a58f8-c9f1-41a4-be37-0f059e0f886f", "dataset_owner": "hwh", "authority_url": "https://www.hetwaterschapshuis.nl/", "automatic_casing": false, "data_epsg": "EPSG:28992", "epsg_list": ["EPSG:28992", "EPSG:25831", "EPSG:25832", "EPSG:3034", "EPSG:3035", "EPSG:3857", "EPSG:4258", "EPSG:4326", "CRS:84"], "templates": "/srv/data/config/templates", "outputformat_jpg": "jpg", "outputformat_png8": "png", "symbols": ["/styling/bridge.symbol", "/styling/x.symbol"], "group_layers": [{"name": "HY.PhysicalWaters.ManMadeObject", "title": "Man-made Object", "abstract": "Crossing line, crossing point, dam or weir, sluice, embankment, lock.", "style_name": "HY.PhysicalWaters.ManMadeObject.Default", "style_title": "Man-made objects default style"}], "layers": [{"name": "HY.PhysicalWaters.Waterbodies", "gpkg_path": "/srv/data/gpkg/Waterbody.gpkg", "tablename": "watercourse", "geometry_type": "MultiLineString", "columns": [{"name": "fuuid"}, {"name": "gml_id"}, {"name": "beginlifespanversion"}, {"name": "condition"}, {"name": "delineationknown"}, {"name": "endlifespanversion"}, {"name": "length"}, {"name": "level"}, {"name": "localid"}, {"name": "localtype"}, {"name": "name"}, {"name": "namespace"}, {"name": "origin"}, {"name": "persistence"}, {"name": "streamorder"}, {"name": "tidal"}, {"name": "widthrange"}], "title": "Waterbody", "abstract": "Watercourse", "keywords": "Hydroobject,Waterbody,Watercourse,River,Stream,Lake,Reservoir", "dataset_metadata_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "dataset_source_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "layer_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "minscale": "1", "maxscale": "50000", "styles": [{"title": "Water bodies default style", "path": "/styling/watercourse.style"}]}, {"name": "HY.PhysicalWaters.Catchments", "gpkg_path": "/srv/data/gpkg/Catchment.gpkg", "tablename": "drainagebasin", "geometry_type": "MultiPolygon", "columns": [{"name": "fuuid"}, {"name": "gml_id"}, {"name": "area"}, {"name": "beginlifespanversion"}, {"name": "endlifespanversion"}, {"name": "localid"}, {"name": "name"}, {"name": "namespace"}, {"name": "order"}, {"name": "orderscheme"}, {"name": "origin"}, {"name": "outlet"}, {"name": "scope"}], "title": "Catchment", "abstract": "Drainage basin", "keywords": "AfvoergebiedAanvoergebied,Catchment,Basin,Catchment Area,Drainage basin", "dataset_metadata_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "dataset_source_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "layer_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "minscale": "1", "maxscale": "50000", "styles": [{"title": "Drainage Basin default style", "path": "/styling/drainagebasin.style"}]}, {"name": "HY.PhysicalWaters.ManMadeObject.lock", "group_name": "HY.PhysicalWaters.ManMadeObject", "gpkg_path": "/srv/data/gpkg/Man-madeObject.gpkg", "tablename": "lock", "geometry_type": "Point", "columns": [{"name": "fuuid"}, {"name": "gml_id"}, {"name": "beginlifespanversion"}, {"name": "condition"}, {"name": "endlifespanversion"}, {"name": "localid"}, {"name": "name"}, {"name": "namespace"}], "title": "Man-made Object", "abstract": "Crossing line, crossing point, dam or weir, sluice, embankment, lock.", "keywords": "Man Made,Duikersifonhevel,Aquaduct,Brug,Stuw,Vastedam,Waterkering,Sluis.", "dataset_metadata_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "dataset_source_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "layer_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "minscale": "1", "maxscale": "50000", "styles": [{"title": "Lock", "path": "/styling/lock.style"}]}, {"name": "HY.PhysicalWaters.ManMadeObject.crossingpoint", "group_name": "HY.PhysicalWaters.ManMadeObject", "gpkg_path": "/srv/data/gpkg/Man-madeObject.gpkg", "tablename": "crossingpoint", "geometry_type": "Point", "columns": [{"name": "fuuid"}, {"name": "gml_id"}, {"name": "beginlifespanversion"}, {"name": "condition"}, {"name": "endlifespanversion"}, {"name": "localid"}, {"name": "name"}, {"name": "namespace"}, {"name": "type"}], "title": "Man-made Object", "abstract": "Crossing line, crossing point, dam or weir, sluice, embankment, lock.", "keywords": "Man Made,Duikersifonhevel,Aquaduct,Brug,Stuw,Vastedam,Waterkering,Sluis.", "dataset_metadata_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "dataset_source_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "layer_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "minscale": "1", "maxscale": "50000", "styles": [{"title": "Crossing Point", "path": "/styling/crossingpoint.style"}]}, {"name": "HY.PhysicalWaters.ManMadeObject.sluice", "group_name": "HY.PhysicalWaters.ManMadeObject", "gpkg_path": "/srv/data/gpkg/Man-madeObject.gpkg", "tablename": "sluice", "geometry_type": "Point", "columns": [{"name": "fuuid"}, {"name": "gml_id"}, {"name": "beginlifespanversion"}, {"name": "condition"}, {"name": "endlifespanversion"}, {"name": "localid"}, {"name": "name"}, {"name": "namespace"}], "title": "Man-made Object", "abstract": "Crossing line, crossing point, dam or weir, sluice, embankment, lock.", "keywords": "Man Made,Duikersifonhevel,Aquaduct,Brug,Stuw,Vastedam,Waterkering,Sluis.", "dataset_metadata_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "dataset_source_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "layer_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "minscale": "1", "maxscale": "50000", "styles": [{"title": "Sluice", "path": "/styling/sluice.style"}]}, {"name": "HY.PhysicalWaters.ManMadeObject.embankment", "group_name": "HY.PhysicalWaters.ManMadeObject", "gpkg_path": "/srv/data/gpkg/Man-madeObject.gpkg", "tablename": "embankment", "geometry_type": "MultiLineString", "columns": [{"name": "fuuid"}, {"name": "gml_id"}, {"name": "beginlifespanversion"}, {"name": "condition"}, {"name": "endlifespanversion"}, {"name": "localid"}, {"name": "name"}, {"name": "namespace"}], "title": "Man-made Object", "abstract": "Crossing line, crossing point, dam or weir, sluice, embankment, lock.", "keywords": "Man Made,Duikersifonhevel,Aquaduct,Brug,Stuw,Vastedam,Waterkering,Sluis.", "dataset_metadata_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "dataset_source_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "layer_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "minscale": "1", "maxscale": "50000", "styles": [{"title": "Embankment", "path": "/styling/embankment.style"}]}, {"name": "HY.PhysicalWaters.ManMadeObject.crossingline", "group_name": "HY.PhysicalWaters.ManMadeObject", "gpkg_path": "/srv/data/gpkg/Man-madeObject.gpkg", "tablename": "crossingline", "geometry_type": "MultiLineString", "columns": [{"name": "fuuid"}, {"name": "gml_id"}, {"name": "beginlifespanversion"}, {"name": "condition"}, {"name": "endlifespanversion"}, {"name": "localid"}, {"name": "name"}, {"name": "namespace"}, {"name": "type"}], "title": "Man-made Object", "abstract": "Crossing line, crossing point, dam or weir, sluice, embankment, lock.", "keywords": "Man Made,Duikersifonhevel,Aquaduct,Brug,Stuw,Vastedam,Waterkering,Sluis.", "dataset_metadata_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "dataset_source_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "layer_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "minscale": "1", "maxscale": "50000", "styles": [{"title": "Crossing Line", "path": "/styling/crossingline.style"}]}, {"name": "HY.PhysicalWaters.ManMadeObject.damorweir", "group_name": "HY.PhysicalWaters.ManMadeObject", "gpkg_path": "/srv/data/gpkg/Man-madeObject.gpkg", "tablename": "damorweir", "geometry_type": "Point", "columns": [{"name": "fuuid"}, {"name": "gml_id"}, {"name": "beginlifespanversion"}, {"name": "condition"}, {"name": "endlifespanversion"}, {"name": "localid"}, {"name": "name"}, {"name": "namespace"}], "title": "Man-made Object", "abstract": "Crossing line, crossing point, dam or weir, sluice, embankment, lock.", "keywords": "Man Made,Duikersifonhevel,Aquaduct,Brug,Stuw,Vastedam,Waterkering,Sluis.", "dataset_metadata_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "dataset_source_id": "07575774-57a1-4419-bab4-6c88fdeb02b2", "layer_extent": "-59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961", "minscale": "1", "maxscale": "50000", "styles": [{"title": "Dam or Weir", "path": "/styling/damorweir.style"}]}]}` + //nolint:misspell WMSGroupAndToplayerConfig = `{"service_title": "Kadastrale Kaart (WMS)", "service_abstract": "Overzicht van de ligging van de kadastrale percelen in Nederland. Fungeert als schakel tussen terrein en registratie, vervult voor externe gebruiker vaak een referentiefunctie, een ondergrond ten opzichte waarvan de gebruiker eigen informatie kan vastleggen en presenteren.", "service_keywords": "Kadaster,Kadastrale percelen,Kadastrale grens,Kadastrale kaart,Bebouwing,Nummeraanduidingreeks,Openbare ruimte naam,Perceel,Grens,Kwaliteit,Kwaliteitslabels,HVD,Geospatiale data", "service_accessconstraints": "https://creativecommons.org/publicdomain/zero/1.0/deed.nl", "service_extent": "-25000 250000 280000 860000", "maxSize": "10000", "service_namespace_prefix": "kadastralekaart", "service_namespace_uri": "http://kadastralekaart.geonovum.nl", "service_onlineresource": "https://service.pdok.nl", "service_path": "/kadaster/kadastralekaart/wms/v5_0", "service_metadata_id": "97cf6a64-9cfc-4ce6-9741-2db44fd27fca", "dataset_owner": "kadaster", "authority_url": "https://www.kadaster.nl", "automatic_casing": true, "data_epsg": "EPSG:28992", "epsg_list": ["EPSG:28992", "EPSG:25831", "EPSG:25832", "EPSG:3034", "EPSG:3035", "EPSG:3857", "EPSG:4258", "EPSG:4326", "CRS:84"], "templates": "/srv/data/config/templates", "fonts": "/srv/data/config/fonts", "top_level_name": "Kadastralekaart", "resolution": "91", "defresolution": "91", "outputformat_jpg": "jpg", "outputformat_png8": "png", "symbols": [], "group_layers": [{"name": "Bebouwing", "title": "Bebouwing", "abstract": "De laag Bebouwing is een selectie op panden van de BGT.", "style_name": "standaard:bebouwing", "style_title": "Standaardvisualisatie Bebouwing"}, {"name": "Perceel", "title": "Perceel", "abstract": "Een perceel is een stuk grond waarvan het Kadaster de grenzen heeft gemeten of gaat meten en dat bij het Kadaster een eigen nummer heeft. Een perceel is een begrensd deel van het Nederlands grondgebied dat kadastraal ge\u00efdentificeerd is en met kadastrale grenzen begrensd is.", "style_name": "standaard:perceel", "style_title": "Standaardvisualisatie Perceel"}], "layers": [{"name": "Bebouwingvlak", "group_name": "Bebouwing", "gpkg_path": "/srv/data/gpkg/pand.gpkg", "tablename": "pand", "geometry_type": "Polygon", "columns": [{"name": "fuuid"}, {"name": "object_begin_tijd"}, {"name": "lv_publicatiedatum", "alias": "LV-publicatiedatum"}, {"name": "relatieve_hoogteligging"}, {"name": "in_onderzoek"}, {"name": "tijdstip_registratie"}, {"name": "identificatie_namespace"}, {"name": "identificatie_lokaal_id", "alias": "identificatieLokaalID"}, {"name": "bronhouder"}, {"name": "bgt_status", "alias": "bgt-status"}, {"name": "plus_status", "alias": "plus-status"}, {"name": "identificatie_bag_pnd", "alias": "identificatieBAGPND"}], "title": "Bebouwingvlak", "abstract": "De laag Bebouwing is een selectie op panden van de BGT.", "keywords": "Bebouwing", "dataset_metadata_id": "a29917b9-3426-4041-a11b-69bcb2256904", "dataset_source_id": "06b6c650-cdb1-11dd-ad8b-0800200c9a64", "layer_extent": "-25000 250000 280000 860000", "minscale": "50", "maxscale": "6001", "styles": [{"title": "Standaardvisualisatie", "path": "/styling/bebouwing.style"}, {"title": "Kwaliteitsvisualisatie", "path": "/styling/bebouwing_kwaliteit.style"}, {"title": "Printvisualisatie", "path": "/styling/bebouwing_print.style"}, {"title": "Standaardvisualisatie Bebouwing", "path": "/styling/bebouwing.group.style"}, {"title": "Kwaliteitsvisualisatie Bebouwing", "path": "/styling/bebouwing_kwaliteit.group.style"}, {"title": "Printvisualisatie Bebouwing", "path": "/styling/bebouwing_print.group.style"}]}, {"name": "Nummeraanduidingreeks", "group_name": "Bebouwing", "gpkg_path": "/srv/data/gpkg/pand_nummeraanduiding.gpkg", "tablename": "pand_nummeraanduiding", "geometry_type": "Point", "columns": [{"name": "fuuid"}, {"name": "bebouwing_id", "alias": "bebouwingID"}, {"name": "hoek"}, {"name": "tekst"}, {"name": "bag_vbo_laagste_huisnummer", "alias": "identificatie_BAGVBOLaagsteHuisnummer"}, {"name": "bag_vbo_hoogste_huisnummer", "alias": "identificatie_BAGVBOHoogsteHuisnummer"}, {"name": "hoek"}], "title": "Nummeraanduidingreeks", "abstract": "De laag Bebouwing is een selectie op panden van de BGT.", "keywords": "Nummeraanduidingreeks", "dataset_metadata_id": "a29917b9-3426-4041-a11b-69bcb2256904", "dataset_source_id": "06b6c650-cdb1-11dd-ad8b-0800200c9a64", "layer_extent": "-25000 250000 280000 860000", "minscale": "50", "maxscale": "2001", "styles": [{"title": "Standaardvisualisatie", "path": "/styling/nummeraanduidingreeks.style"}, {"title": "Kwaliteitsvisualisatie", "path": "/styling/nummeraanduidingreeks_kwaliteit.style"}, {"title": "Printvisualisatie", "path": "/styling/nummeraanduidingreeks_print.style"}, {"title": "Standaardvisualisatie Bebouwing", "path": "/styling/nummeraanduidingreeks.group.style"}, {"title": "Kwaliteitsvisualisatie Bebouwing", "path": "/styling/nummeraanduidingreeks_kwaliteit.group.style"}, {"title": "Printvisualisatie Bebouwing", "path": "/styling/nummeraanduidingreeks_print.group.style"}]}, {"name": "OpenbareRuimteNaam", "gpkg_path": "/srv/data/gpkg/openbareruimtelabel.gpkg", "tablename": "openbareruimtelabel", "geometry_type": "Point", "columns": [{"name": "fuuid"}, {"name": "object_begin_tijd"}, {"name": "lv_publicatiedatum", "alias": "LV-publicatiedatum"}, {"name": "relatieve_hoogteligging"}, {"name": "in_onderzoek"}, {"name": "tijdstip_registratie"}, {"name": "identificatie_namespace"}, {"name": "identificatie_lokaal_id", "alias": "identificatieLokaalID"}, {"name": "bronhouder"}, {"name": "bgt_status", "alias": "bgt-status"}, {"name": "plus_status", "alias": "plus-status"}, {"name": "identificatie_bag_opr", "alias": "identificatieBAGOPR"}, {"name": "tekst"}, {"name": "hoek"}, {"name": "openbare_ruimte_type"}], "title": "OpenbareRuimteNaam", "abstract": "De laag Openbareruimtenaam is een selectie op de openbare ruimte labels van de BGT met een bgt-status \"bestaand\" die een classificatie (openbareruimtetype) Weg en Water hebben.", "keywords": "Openbare ruimte naam", "dataset_metadata_id": "a29917b9-3426-4041-a11b-69bcb2256904", "dataset_source_id": "06b6c650-cdb1-11dd-ad8b-0800200c9a64", "layer_extent": "-25000 250000 280000 860000", "minscale": "50", "maxscale": "2001", "styles": [{"title": "Standaardvisualisatie", "path": "/styling/openbareruimtenaam.style"}, {"title": "Kwaliteitsvisualisatie", "path": "/styling/openbareruimtenaam_kwaliteit.style"}, {"title": "Printvisualisatie", "path": "/styling/openbareruimtenaam_print.style"}, {"title": "Standaardvisualisatie OpenbareRuimteNaam", "path": "/styling/openbareruimtenaam.group.style"}, {"title": "Kwaliteitsvisualisatie OpenbareRuimteNaam", "path": "/styling/openbareruimtenaam_kwaliteit.group.style"}, {"title": "Printvisualisatie OpenbareRuimteNaam", "path": "/styling/openbareruimtenaam_print.group.style"}]}, {"name": "Perceelvlak", "group_name": "Perceel", "gpkg_path": "/srv/data/gpkg/perceel.gpkg", "tablename": "perceel", "geometry_type": "Polygon", "columns": [{"name": "fuuid"}, {"name": "identificatie_namespace"}, {"name": "identificatie_lokaal_id", "alias": "identificatieLokaalID"}, {"name": "begin_geldigheid"}, {"name": "tijdstip_registratie"}, {"name": "volgnummer"}, {"name": "status_historie_code"}, {"name": "status_historie_waarde"}, {"name": "kadastrale_gemeente_code"}, {"name": "kadastrale_gemeente_waarde"}, {"name": "sectie"}, {"name": "akr_kadastrale_gemeente_code_code", "alias": "AKRKadastraleGemeenteCodeCode"}, {"name": "akr_kadastrale_gemeente_code_waarde", "alias": "AKRKadastraleGemeenteCodeWaarde"}, {"name": "kadastrale_grootte_waarde"}, {"name": "soort_grootte_code"}, {"name": "soort_grootte_waarde"}, {"name": "perceelnummer"}, {"name": "perceelnummer_rotatie"}, {"name": "perceelnummer_verschuiving_delta_x"}, {"name": "perceelnummer_verschuiving_delta_y"}, {"name": "perceelnummer_plaatscoordinaat_x"}, {"name": "perceelnummer_plaatscoordinaat_y"}], "title": "Perceelvlak", "abstract": "Een perceel is een stuk grond waarvan het Kadaster de grenzen heeft gemeten of gaat meten en dat bij het Kadaster een eigen nummer heeft. Een perceel is een begrensd deel van het Nederlands grondgebied dat kadastraal ge\u00efdentificeerd is en met kadastrale grenzen begrensd is.", "keywords": "Kadastrale percelen", "dataset_metadata_id": "a29917b9-3426-4041-a11b-69bcb2256904", "dataset_source_id": "06b6c650-cdb1-11dd-ad8b-0800200c9a64", "layer_extent": "-25000 250000 280000 860000", "minscale": "50", "maxscale": "6001", "styles": [{"title": "Standaardvisualisatie", "path": "/styling/perceelvlak.style"}, {"title": "Kwaliteitsvisualisatie", "path": "/styling/perceelvlak_kwaliteit.style"}, {"title": "Printvisualisatie", "path": "/styling/perceelvlak_print.style"}, {"title": "Standaardvisualisatie Perceel", "path": "/styling/perceelvlak.group.style"}, {"title": "Kwaliteitsvisualisatie Perceel", "path": "/styling/perceelvlak_kwaliteit.group.style"}, {"title": "Printvisualisatie Perceel", "path": "/styling/perceelvlak_print.group.style"}]}, {"name": "Label", "group_name": "Perceel", "gpkg_path": "/srv/data/gpkg/perceel_label.gpkg", "tablename": "perceel_label", "geometry_type": "Point", "columns": [{"name": "fuuid"}, {"name": "perceel_id", "alias": "perceelID"}, {"name": "perceelnummer"}, {"name": "rotatie"}, {"name": "verschuiving_delta_x"}, {"name": "verschuiving_delta_y"}], "title": "Label", "abstract": "Een perceel is een stuk grond waarvan het Kadaster de grenzen heeft gemeten of gaat meten en dat bij het Kadaster een eigen nummer heeft. Een perceel is een begrensd deel van het Nederlands grondgebied dat kadastraal ge\u00efdentificeerd is en met kadastrale grenzen begrensd is.", "keywords": "Kadastrale percelen", "dataset_metadata_id": "a29917b9-3426-4041-a11b-69bcb2256904", "dataset_source_id": "06b6c650-cdb1-11dd-ad8b-0800200c9a64", "layer_extent": "-25000 250000 280000 860000", "minscale": "50", "maxscale": "6001", "styles": [{"title": "Standaardvisualisatie", "path": "/styling/label.style"}, {"title": "Standaardvisualisatie Perceel", "path": "/styling/label.group.style"}, {"title": "Kwaliteitsvisualisatie", "path": "/styling/label_kwaliteit.style"}, {"title": "Kwaliteitsvisualisatie Perceel", "path": "/styling/label_kwaliteit.group.style"}, {"title": "Printvisualisatie", "path": "/styling/label_print.style"}, {"title": "Printvisualisatie Perceel", "path": "/styling/label_print.group.style"}]}, {"name": "Bijpijling", "group_name": "Perceel", "gpkg_path": "/srv/data/gpkg/perceel_bijpijling.gpkg", "tablename": "perceel_bijpijling", "geometry_type": "LineString", "columns": [{"name": "fuuid"}, {"name": "perceel_id", "alias": "perceelID"}], "title": "Bijpijling", "abstract": "Een perceel is een stuk grond waarvan het Kadaster de grenzen heeft gemeten of gaat meten en dat bij het Kadaster een eigen nummer heeft. Een perceel is een begrensd deel van het Nederlands grondgebied dat kadastraal ge\u00efdentificeerd is en met kadastrale grenzen begrensd is.", "keywords": "Kadastrale percelen", "dataset_metadata_id": "a29917b9-3426-4041-a11b-69bcb2256904", "dataset_source_id": "06b6c650-cdb1-11dd-ad8b-0800200c9a64", "layer_extent": "-25000 250000 280000 860000", "minscale": "50", "maxscale": "6001", "styles": [{"title": "Standaardvisualisatie", "path": "/styling/bijpijling.style"}, {"title": "Kwaliteitsvisualisatie", "path": "/styling/bijpijling_kwaliteit.style"}, {"title": "Printvisualisatie", "path": "/styling/bijpijling_print.style"}, {"title": "Standaardvisualisatie Perceel", "path": "/styling/bijpijling.group.style"}, {"title": "Kwaliteitsvisualisatie Perceel", "path": "/styling/bijpijling_kwaliteit.group.style"}, {"title": "Printvisualisatie Perceel", "path": "/styling/bijpijling_print.group.style"}]}, {"name": "KadastraleGrens", "gpkg_path": "/srv/data/gpkg/kadastrale_grens.gpkg", "tablename": "kadastrale_grens", "geometry_type": "LineString", "columns": [{"name": "fuuid"}, {"name": "begin_geldigheid"}, {"name": "tijdstip_registratie"}, {"name": "volgnummer"}, {"name": "status_historie_code"}, {"name": "status_historie_waarde"}, {"name": "identificatie_namespace"}, {"name": "identificatie_lokaal_id", "alias": "identificatieLokaalID"}, {"name": "type_grens_code"}, {"name": "type_grens_waarde"}, {"name": "classificatie_kwaliteit_code", "alias": "ClassificatieKwaliteitCode"}, {"name": "classificatie_kwaliteit_waarde", "alias": "ClassificatieKwaliteitWaarde"}, {"name": "perceel_links_identificatie_namespace"}, {"name": "perceel_links_identificatie_lokaal_id", "alias": "perceelLinksIdentificatieLokaalID"}, {"name": "perceel_rechts_identificatie_namespace"}, {"name": "perceel_rechts_identificatie_lokaal_id", "alias": "perceelRechtsIdentificatieLokaalID"}], "title": "KadastraleGrens", "abstract": "Een Kadastrale Grens is de weergave van een grens op de kadastrale kaart die door de dienst van het Kadaster tussen percelen (voorlopig) vastgesteld wordt, op basis van inlichtingen van belanghebbenden en met gebruikmaking van de aan de kadastrale kaart ten grondslag liggende bescheiden die in elk geval de landmeetkundige gegevens bevatten van hetgeen op die kaart wordt weergegeven.", "keywords": "Grens,Kadastrale grenzen", "dataset_metadata_id": "a29917b9-3426-4041-a11b-69bcb2256904", "dataset_source_id": "06b6c650-cdb1-11dd-ad8b-0800200c9a64", "layer_extent": "-25000 250000 280000 860000", "minscale": "50", "maxscale": "6001", "styles": [{"title": "Standaardvisualisatie", "path": "/styling/kadastralegrens.style"}, {"title": "Kwaliteitsvisualisatie", "path": "/styling/kadastralegrens_kwaliteit.style"}, {"title": "Printvisualisatie", "path": "/styling/kadastralegrens_print.style"}, {"title": "Standaardvisualisatie KadastraleGrens", "path": "/styling/kadastralegrens.group.style"}, {"title": "Kwaliteitsvisualisatie KadastraleGrens", "path": "/styling/kadastralegrens_kwaliteit.group.style"}, {"title": "Printvisualisatie KadastraleGrens", "path": "/styling/kadastralegrens_print.group.style"}]}]}` WMSTifConfig = `{"service_title": "Luchtfoto Labels WMS", "service_abstract": "De luchtfoto labels bestaan uit weglabels en wegassen en kunnen worden gebruikt als laag (overlay) op onder andere de PDOK luchtfoto.", "service_keywords": "bzk,luchtfotolabels", "service_accessconstraints": "https://creativecommons.org/publicdomain/zero/1.0/deed.nl", "service_extent": "-25000 250000 280000 860000", "maxSize": "4000", "service_namespace_prefix": "luchtfotolabels", "service_namespace_uri": "http://luchtfotolabels.geonovum.nl", "service_onlineresource": "https://service.pdok.nl", "service_path": "/bzk/luchtfotolabels/wms/v1_0", "service_metadata_id": "70562932-e7dc-4ba2-ba4f-05863d02587c", "dataset_owner": "kadaster", "authority_url": "http://www.kadaster.nl", "automatic_casing": false, "data_epsg": "EPSG:28992", "epsg_list": ["EPSG:28992", "EPSG:25831", "EPSG:25832", "EPSG:3034", "EPSG:3035", "EPSG:3857", "EPSG:4258", "EPSG:4326", "CRS:84"], "templates": "/srv/data/config/templates", "outputformat_jpg": "jpg", "outputformat_png8": "png", "symbols": [], "group_layers": [{"name": "lufolabels", "title": "Luchtfoto labels", "abstract": "De luchtfoto labels bestaan uit weglabels en wegassen en kunnen worden gebruikt als laag (overlay) op onder andere de PDOK luchtfoto.", "style_name": "luchtfotolabels", "style_title": "Luchtfotolabels"}], "layers": [{"name": "luchtfotoroads_100pixkm", "group_name": "lufolabels", "resample": "BILINEAR", "tif_path": "/srv/data/tif/100pixkm_luforoads.vrt", "geometry_type": "Raster", "offsite": "#978E97", "get_feature_info_includes_class": false, "title": "Luchtfoto roads 100pixkm", "abstract": "De luchtfoto labels bestaan uit weglabels en wegassen en kunnen worden gebruikt als laag (overlay) op onder andere de PDOK luchtfoto.", "keywords": "bzk,luchtfotolabels", "dataset_metadata_id": "6ca22f53-b072-42f4-b920-104c7c83cd28", "dataset_source_id": "901647c2-802d-11e6-ae22-56b6b6499611", "layer_extent": "-25000 250000 280000 860000", "minscale": "24001", "maxscale": "48001", "styles": [{"title": "Luchtfotolabels", "path": "/styling/roads.style"}]}, {"name": "luchtfotoroads_200pixkm", "group_name": "lufolabels", "resample": "BILINEAR", "tif_path": "/srv/data/tif/200pixkm_luforoads.vrt", "geometry_type": "Raster", "offsite": "#978E97", "get_feature_info_includes_class": false, "title": "Luchtfoto roads 200pixkm", "abstract": "De luchtfoto labels bestaan uit weglabels en wegassen en kunnen worden gebruikt als laag (overlay) op onder andere de PDOK luchtfoto.", "keywords": "bzk,luchtfotolabels", "dataset_metadata_id": "6ca22f53-b072-42f4-b920-104c7c83cd28", "dataset_source_id": "901647c2-802d-11e6-ae22-56b6b6499611", "layer_extent": "-25000 250000 280000 860000", "minscale": "12001", "maxscale": "24001", "styles": [{"title": "Luchtfotolabels", "path": "/styling/roads.style"}]}, {"name": "luchtfotoroads_400pixkm", "group_name": "lufolabels", "resample": "BILINEAR", "tif_path": "/srv/data/tif/400pixkm_luforoads.vrt", "geometry_type": "Raster", "offsite": "#978E97", "get_feature_info_includes_class": false, "title": "Luchtfoto roads 400pixkm", "abstract": "De luchtfoto labels bestaan uit weglabels en wegassen en kunnen worden gebruikt als laag (overlay) op onder andere de PDOK luchtfoto.", "keywords": "bzk,luchtfotolabels", "dataset_metadata_id": "6ca22f53-b072-42f4-b920-104c7c83cd28", "dataset_source_id": "901647c2-802d-11e6-ae22-56b6b6499611", "layer_extent": "-25000 250000 280000 860000", "minscale": "6001", "maxscale": "12001", "styles": [{"title": "Luchtfotolabels", "path": "/styling/roads.style"}]}, {"name": "luchtfotoroads_800pixkm", "group_name": "lufolabels", "resample": "BILINEAR", "tif_path": "/srv/data/tif/800pixkm_luforoads.vrt", "geometry_type": "Raster", "offsite": "#978E97", "get_feature_info_includes_class": false, "title": "Luchtfoto roads 800pixkm", "abstract": "De luchtfoto labels bestaan uit weglabels en wegassen en kunnen worden gebruikt als laag (overlay) op onder andere de PDOK luchtfoto.", "keywords": "bzk,luchtfotolabels", "dataset_metadata_id": "6ca22f53-b072-42f4-b920-104c7c83cd28", "dataset_source_id": "901647c2-802d-11e6-ae22-56b6b6499611", "layer_extent": "-25000 250000 280000 860000", "minscale": "3001", "maxscale": "6001", "styles": [{"title": "Luchtfotolabels", "path": "/styling/roads.style"}]}, {"name": "luchtfotoroads_1600pixkm", "group_name": "lufolabels", "resample": "BILINEAR", "tif_path": "/srv/data/tif/1600pixkm_luforoads.vrt", "geometry_type": "Raster", "offsite": "#978E97", "get_feature_info_includes_class": false, "title": "Luchtfoto roads 1600pixkm", "abstract": "De luchtfoto labels bestaan uit weglabels en wegassen en kunnen worden gebruikt als laag (overlay) op onder andere de PDOK luchtfoto.", "keywords": "bzk,luchtfotolabels", "dataset_metadata_id": "6ca22f53-b072-42f4-b920-104c7c83cd28", "dataset_source_id": "901647c2-802d-11e6-ae22-56b6b6499611", "layer_extent": "-25000 250000 280000 860000", "minscale": "1501", "maxscale": "3001", "styles": [{"title": "Luchtfotolabels", "path": "/styling/roads.style"}]}, {"name": "luchtfotolabels_100pixkm", "group_name": "lufolabels", "resample": "BILINEAR", "tif_path": "/srv/data/tif/100pixkm_lufolabels.vrt", "geometry_type": "Raster", "offsite": "#978E97", "get_feature_info_includes_class": false, "title": "Luchtfoto labels 100pixkm", "abstract": "De luchtfoto labels bestaan uit weglabels en wegassen en kunnen worden gebruikt als laag (overlay) op onder andere de PDOK luchtfoto.", "keywords": "bzk,luchtfotolabels", "dataset_metadata_id": "6ca22f53-b072-42f4-b920-104c7c83cd28", "dataset_source_id": "901647c2-802d-11e6-ae22-56b6b6499611", "layer_extent": "-25000 250000 280000 860000", "minscale": "24001", "maxscale": "48001", "styles": [{"title": "Luchtfotolabels", "path": "/styling/labels.style"}]}, {"name": "luchtfotolabels_200pixkm", "group_name": "lufolabels", "resample": "BILINEAR", "tif_path": "/srv/data/tif/200pixkm_lufolabels.vrt", "geometry_type": "Raster", "offsite": "#978E97", "get_feature_info_includes_class": false, "title": "Luchtfoto labels 200pixkm", "abstract": "De luchtfoto labels bestaan uit weglabels en wegassen en kunnen worden gebruikt als laag (overlay) op onder andere de PDOK luchtfoto.", "keywords": "bzk,luchtfotolabels", "dataset_metadata_id": "6ca22f53-b072-42f4-b920-104c7c83cd28", "dataset_source_id": "901647c2-802d-11e6-ae22-56b6b6499611", "layer_extent": "-25000 250000 280000 860000", "minscale": "12001", "maxscale": "24001", "styles": [{"title": "Luchtfotolabels", "path": "/styling/labels.style"}]}, {"name": "luchtfotolabels_400pixkm", "group_name": "lufolabels", "resample": "BILINEAR", "tif_path": "/srv/data/tif/400pixkm_lufolabels.vrt", "geometry_type": "Raster", "offsite": "#978E97", "get_feature_info_includes_class": false, "title": "Luchtfoto labels 400pixkm", "abstract": "De luchtfoto labels bestaan uit weglabels en wegassen en kunnen worden gebruikt als laag (overlay) op onder andere de PDOK luchtfoto.", "keywords": "bzk,luchtfotolabels", "dataset_metadata_id": "6ca22f53-b072-42f4-b920-104c7c83cd28", "dataset_source_id": "901647c2-802d-11e6-ae22-56b6b6499611", "layer_extent": "-25000 250000 280000 860000", "minscale": "6001", "maxscale": "12001", "styles": [{"title": "Luchtfotolabels", "path": "/styling/labels.style"}]}, {"name": "luchtfotolabels_800pixkm", "group_name": "lufolabels", "resample": "BILINEAR", "tif_path": "/srv/data/tif/800pixkm_lufolabels.vrt", "geometry_type": "Raster", "offsite": "#978E97", "get_feature_info_includes_class": false, "title": "Luchtfoto labels 800pixkm", "abstract": "De luchtfoto labels bestaan uit weglabels en wegassen en kunnen worden gebruikt als laag (overlay) op onder andere de PDOK luchtfoto.", "keywords": "bzk,luchtfotolabels", "dataset_metadata_id": "6ca22f53-b072-42f4-b920-104c7c83cd28", "dataset_source_id": "901647c2-802d-11e6-ae22-56b6b6499611", "layer_extent": "-25000 250000 280000 860000", "minscale": "3001", "maxscale": "6001", "styles": [{"title": "Luchtfotolabels", "path": "/styling/labels.style"}]}, {"name": "luchtfotolabels_1600pixkm", "group_name": "lufolabels", "resample": "BILINEAR", "tif_path": "/srv/data/tif/1600pixkm_lufolabels.vrt", "geometry_type": "Raster", "offsite": "#978E97", "get_feature_info_includes_class": false, "title": "Luchtfoto labels 1600pixkm", "abstract": "De luchtfoto labels bestaan uit weglabels en wegassen en kunnen worden gebruikt als laag (overlay) op onder andere de PDOK luchtfoto.", "keywords": "bzk,luchtfotolabels", "dataset_metadata_id": "6ca22f53-b072-42f4-b920-104c7c83cd28", "dataset_source_id": "901647c2-802d-11e6-ae22-56b6b6499611", "layer_extent": "-25000 250000 280000 860000", "minscale": "1501", "maxscale": "3001", "styles": [{"title": "Luchtfotolabels", "path": "/styling/labels.style"}]}, {"name": "luchtfotolabels_3200pixkm", "group_name": "lufolabels", "resample": "BILINEAR", "tif_path": "/srv/data/tif/3200pixkm_lufolabels.vrt", "geometry_type": "Raster", "offsite": "#978E97", "get_feature_info_includes_class": false, "title": "Luchtfoto labels 3200pixkm", "abstract": "De luchtfoto labels bestaan uit weglabels en wegassen en kunnen worden gebruikt als laag (overlay) op onder andere de PDOK luchtfoto.", "keywords": "bzk,luchtfotolabels", "dataset_metadata_id": "6ca22f53-b072-42f4-b920-104c7c83cd28", "dataset_source_id": "901647c2-802d-11e6-ae22-56b6b6499611", "layer_extent": "-25000 250000 280000 860000", "maxscale": "1501", "styles": [{"title": "Luchtfotolabels", "path": "/styling/labels.style"}]}]}` WMSPostgisConfig = `{"service_title": "BRT Terugmeldingen WMS", "service_abstract": "De BRT terugmeldingenservice bevat alle recente meldingen op BRT objecten waar twijfel over de juistheid bestaat. Zowel terugmeldingen op de TOP10 als meldingen die gemaakt zijn op de gegeneraliseerde kaartproducten (TOP25, TOP50, TOP100, TOP250) worden hierin geregistreerd. Daarnaast kan je de inhoud en status van de meldingen inzien. Ook een vermoedelijke fout geconstateerd? Doe een melding op https://verbeterdekaart.kadaster.nl", "service_keywords": "Basisregistratie Topografie,BRT,terugmeldingen,TOP10NL,TOP25,TOP50,TOP100,TOP250,in onderzoek register,verbeter de kaart,verbeterdekaart", "service_accessconstraints": "https://creativecommons.org/publicdomain/zero/1.0/deed.nl", "service_extent": "-7000 289000 300000 629000", "maxSize": "4000", "service_namespace_prefix": "terugmeldingen", "service_namespace_uri": "http://terugmeldingen.geonovum.nl", "service_onlineresource": "https://service.pdok.nl", "service_path": "/brt/terugmeldingen/wms/v1_0", "service_metadata_id": "fa069f74-9837-4d63-b2ac-b337b5de86b1", "dataset_owner": "brt", "authority_url": "http://www.brt.nl", "automatic_casing": true, "data_epsg": "EPSG:28992", "epsg_list": ["EPSG:28992", "EPSG:25831", "EPSG:25832", "EPSG:3034", "EPSG:3035", "EPSG:3857", "EPSG:4258", "EPSG:4326", "CRS:84"], "templates": "/srv/data/config/templates", "outputformat_jpg": "jpg", "outputformat_png8": "png", "symbols": ["/styling/terugmeldingen.symbol"], "group_layers": [], "layers": [{"name": "brtterugmeldingen", "tablename": "brtterugmeldingen.brtterugmeldingen_v1", "geometry_type": "Point", "columns": [{"name": "fuuid"}, {"name": "meldingsnummer_volledig"}, {"name": "tijdstip_registratie"}, {"name": "status"}, {"name": "omschrijving"}, {"name": "bronhoudercode"}, {"name": "bronhoudernaam"}, {"name": "tijdstip_statuswijziging"}, {"name": "toelichting"}, {"name": "objectid"}, {"name": "objecttype"}, {"name": "hoogte_vanaf_maaiveld"}], "postgis": true, "title": "BRT Terugmeldingen", "abstract": "Alle recente BRT terugmeldingen gedaan door BRT gebruikers.", "keywords": "brtterugmeldingen", "dataset_metadata_id": "7a84c4de-4ec0-4202-a8d0-792fb7d39d1f", "dataset_source_id": "07c7d650-cdb1-11dd-ad8b-0800200c9a60", "layer_extent": "-7000 289000 300000 629000", "styles": [{"title": "Terugmeldingen", "path": "/styling/terugmeldingen.style"}]}]}` @@ -220,7 +224,7 @@ func TestGetConfigForWFS(t *testing.T) { }, ownerInfo: &smoothoperatorv1.OwnerInfo{ Spec: smoothoperatorv1.OwnerInfoSpec{ - NamespaceTemplate: "http://{{prefix}}.geonovum.nl", + NamespaceTemplate: smoothoperatorutils.Pointer("http://{{prefix}}.geonovum.nl"), }, }, }, @@ -244,10 +248,11 @@ func TestGetConfigForWFS(t *testing.T) { func TestGetConfigForWMSWithNoGroupLayers(t *testing.T) { ownerInfo := &smoothoperatorv1.OwnerInfo{ Spec: smoothoperatorv1.OwnerInfoSpec{ - NamespaceTemplate: "http://{{prefix}}.geonovum.nl", + NamespaceTemplate: smoothoperatorutils.Pointer("http://{{prefix}}.geonovum.nl"), }, } + //nolint:misspell v2wmsstring := "apiVersion: pdok.nl/v2beta1\nkind: WMS\nmetadata:\n name: rws-nwbwegen-v1-0\n labels:\n dataset-owner: rws\n dataset: nwbwegen\n service-version: v1_0\n service-type: wms\n annotations:\n lifecycle-phase: prod\n service-bundle-id: b39c152b-393b-52f5-a50c-e1ffe904b6fb\nspec:\n general:\n datasetOwner: rws\n dataset: nwbwegen\n serviceVersion: v1_0\n kubernetes:\n healthCheck:\n boundingbox: 135134.89,457152.55,135416.03,457187.82\n resources:\n limits:\n ephemeralStorage: 1535Mi\n memory: 4G\n requests:\n cpu: 2000m\n ephemeralStorage: 1535Mi\n memory: 4G\n options:\n automaticCasing: true\n disableWebserviceProxy: false\n includeIngress: true\n validateRequests: true\n service:\n title: NWB - Wegen WMS\n abstract:\n Dit is de web map service van het Nationaal Wegen Bestand (NWB) - wegen.\n Deze dataset bevat alleen de wegvakken en hectometerpunten. Het Nationaal Wegen\n Bestand - Wegen is een digitaal geografisch bestand van alle wegen in Nederland.\n Opgenomen zijn alle wegen die worden beheerd door wegbeheerders als het Rijk,\n provincies, gemeenten en waterschappen, echter alleen voor zover deze zijn voorzien\n van een straatnaam of nummer.\n authority:\n name: rws\n url: https://www.rijkswaterstaat.nl\n dataEPSG: EPSG:28992\n extent: -59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961\n inspire: true\n keywords:\n - Vervoersnetwerken\n - Menselijke gezondheid en veiligheid\n - Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai)\n - Nationaal\n - Voertuigen\n - Verkeer\n - Wegvakken\n - Hectometerpunten\n - HVD\n - Mobiliteit\n stylingAssets:\n configMapRefs:\n - name: includes\n keys:\n - nwb_wegen_hectopunten.symbol\n - hectopunten.style\n - wegvakken.style\n blobKeys:\n - resources/fonts/liberation-sans.ttf\n layers:\n - abstract:\n Deze laag bevat de wegvakken uit het Nationaal Wegen bestand (NWB)\n en geeft gedetailleerde informatie per wegvak zoals straatnaam, wegnummer,\n routenummer, wegbeheerder, huisnummers, enz. weer.\n data:\n gpkg:\n columns:\n - objectid\n - wvk_id\n - wvk_begdat\n - jte_id_beg\n - jte_id_end\n - wegbehsrt\n - wegnummer\n - wegdeelltr\n - hecto_lttr\n - bst_code\n - rpe_code\n - admrichtng\n - rijrichtng\n - stt_naam\n - stt_bron\n - wpsnaam\n - gme_id\n - gme_naam\n - hnrstrlnks\n - hnrstrrhts\n - e_hnr_lnks\n - e_hnr_rhts\n - l_hnr_lnks\n - l_hnr_rhts\n - begafstand\n - endafstand\n - beginkm\n - eindkm\n - pos_tv_wol\n - wegbehcode\n - wegbehnaam\n - distrcode\n - distrnaam\n - dienstcode\n - dienstnaam\n - wegtype\n - wgtype_oms\n - routeltr\n - routenr\n - routeltr2\n - routenr2\n - routeltr3\n - routenr3\n - routeltr4\n - routenr4\n - wegnr_aw\n - wegnr_hmp\n - geobron_id\n - geobron_nm\n - bronjaar\n - openlr\n - bag_orl\n - frc\n - fow\n - alt_naam\n - alt_nr\n - rel_hoogte\n - st_lengthshape\n geometryType: MultiLineString\n blobKey: geopackages/rws/nwbwegen/410a6d1e-e767-41b4-ba8d-9e1e955dd013/1/nwb_wegen.gpkg\n table: wegvakken\n datasetMetadataIdentifier: a9b7026e-0a81-4813-93bd-ba49e6f28502\n keywords:\n - Vervoersnetwerken\n - Menselijke gezondheid en veiligheid\n - Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai)\n - Nationaal\n - Voertuigen\n - Verkeer\n - Wegvakken\n maxScale: 50000.0\n minScale: 1.0\n name: wegvakken\n sourceMetadataIdentifier: 8f0497f0-dbd7-4bee-b85a-5fdec484a7ff\n styles:\n - name: wegvakken\n title: NWB - Wegvakken\n visualization: wegvakken.style\n title: Wegvakken\n visible: true\n - abstract:\n Deze laag bevat de hectopunten uit het Nationaal Wegen Bestand (NWB)\n en geeft gedetailleerde informatie per hectopunt zoals hectometrering, afstand,\n zijde en hectoletter weer.\n data:\n gpkg:\n columns:\n - objectid\n - hectomtrng\n - afstand\n - wvk_id\n - wvk_begdat\n - zijde\n - hecto_lttr\n geometryType: MultiPoint\n blobKey: geopackages/rws/nwbwegen/410a6d1e-e767-41b4-ba8d-9e1e955dd013/1/nwb_wegen.gpkg\n table: hectopunten\n datasetMetadataIdentifier: a9b7026e-0a81-4813-93bd-ba49e6f28502\n keywords:\n - Vervoersnetwerken\n - Menselijke gezondheid en veiligheid\n - Geluidsbelasting hoofdwegen (Richtlijn Omgevingslawaai)\n - Nationaal\n - Voertuigen\n - Verkeer\n - Hectometerpunten\n maxScale: 50000.0\n minScale: 1.0\n name: hectopunten\n sourceMetadataIdentifier: 8f0497f0-dbd7-4bee-b85a-5fdec484a7ff\n styles:\n - name: hectopunten\n title: NWB - Hectopunten\n visualization: hectopunten.style\n title: Hectopunten\n visible: true\n metadataIdentifier: f2437a92-ddd3-4777-a1bc-fdf4b4a7fcb8\n" var v2wms v2beta1.WMS err := yaml.Unmarshal([]byte(v2wmsstring), &v2wms) @@ -269,10 +274,11 @@ func TestGetConfigForWMSWithNoGroupLayers(t *testing.T) { func TestGetConfigForWMSWithGroupLayers(t *testing.T) { ownerInfo := &smoothoperatorv1.OwnerInfo{ Spec: smoothoperatorv1.OwnerInfoSpec{ - NamespaceTemplate: "http://{{prefix}}.geonovum.nl", + NamespaceTemplate: smoothoperatorutils.Pointer("http://{{prefix}}.geonovum.nl"), }, } + //nolint:misspell v2wmsstring := "apiVersion: pdok.nl/v2beta1\nkind: WMS\nmetadata:\n name: hwh-hydrografie-v2-0\n labels:\n dataset-owner: hwh\n dataset: hydrografie\n service-version: v2_0\n service-type: wms\n annotations:\n lifecycle-phase: prod\n service-bundle-id: d30bdf62-1c12-45a5-a57d-367e642ef118\nspec:\n general:\n datasetOwner: hwh\n dataset: hydrografie\n serviceVersion: v2_0\n kubernetes:\n resources:\n limits:\n ephemeralStorage: 1544Mi\n requests:\n ephemeralStorage: 1544Mi\n service:\n title: Waterschappen Hydrografie (INSPIRE geharmoniseerd) WMS\n abstract:\n \"Deze dataset is gebaseerd op (niet geharmoniseerde) data van alle waterschappen\n in Nederland conform INSPIRE. De dataset bevat de volgende INSPIRE objecten:\n CrossingLine, CrossingPoint, DamOrWeir, DrainageBasin, Embankment, Lock, Sluice,\n Watercourse.\"\n authority:\n name: hwh\n url: https://www.hetwaterschapshuis.nl/\n dataEPSG: EPSG:28992\n extent: -59188.44333693248 304984.64144318487 308126.88473339565 858328.516489961\n inspire: true\n keywords:\n - Aquaduct\n - Brug\n - Duikersifonhevel\n - Stuw\n - Vastedam\n - AfvoerAanvoergebied\n - Waterkering\n - Sluis\n - HydroObject\n - HVD\n - Aardobservatie en milieu\n metadataIdentifier: 871a58f8-c9f1-41a4-be37-0f059e0f886f\n stylingAssets:\n configMapRefs:\n - name: includes\n keys:\n - bridge.symbol\n - x.symbol\n blobKeys:\n - resources/images/hwh/hydrografie/bridge.png\n layers:\n - abstract: Watercourse\n data:\n gpkg:\n blobKey: geopackages/hwh/hydrografie/aaa/1/Waterbody.gpkg\n columns:\n - gml_id\n - beginlifespanversion\n - condition\n - delineationknown\n - endlifespanversion\n - length\n - level\n - localid\n - localtype\n - name\n - namespace\n - origin\n - persistence\n - streamorder\n - tidal\n - widthrange\n geometryType: MultiLineString\n table: watercourse\n datasetMetadataIdentifier: 07575774-57a1-4419-bab4-6c88fdeb02b2\n keywords:\n - Hydroobject\n - Waterbody\n - Watercourse\n - River\n - Stream\n - Lake\n - Reservoir\n name: HY.PhysicalWaters.Waterbodies\n sourceMetadataIdentifier: 07575774-57a1-4419-bab4-6c88fdeb02b2\n styles:\n - name: HY.PhysicalWaters.Waterbodies.Default\n title: Water bodies default style\n visualization: watercourse.style\n title: Waterbody\n maxScale: 50000.0\n minScale: 1.0\n visible: true\n - abstract: Drainage basin\n data:\n gpkg:\n blobKey: geopackages/hwh/hydrografie/aaa/1/Catchment.gpkg\n columns:\n - gml_id\n - area\n - beginlifespanversion\n - endlifespanversion\n - localid\n - name\n - namespace\n - order\n - orderscheme\n - origin\n - outlet\n - scope\n geometryType: MultiPolygon\n table: drainagebasin\n datasetMetadataIdentifier: 07575774-57a1-4419-bab4-6c88fdeb02b2\n keywords:\n - AfvoergebiedAanvoergebied\n - Catchment\n - Basin\n - Catchment Area\n - Drainage basin\n name: HY.PhysicalWaters.Catchments\n sourceMetadataIdentifier: 07575774-57a1-4419-bab4-6c88fdeb02b2\n styles:\n - name: HY.PhysicalWaters.Catchments.Default\n title: Drainage Basin default style\n visualization: drainagebasin.style\n title: Catchment\n maxScale: 50000.0\n minScale: 1.0\n visible: true\n - abstract: Crossing line, crossing point, dam or weir, sluice, embankment, lock.\n datasetMetadataIdentifier: 07575774-57a1-4419-bab4-6c88fdeb02b2\n keywords:\n - Man Made\n - Duikersifonhevel\n - Aquaduct\n - Brug\n - Stuw\n - Vastedam\n - Waterkering\n - Sluis\n - Bridge\n - Aquaduct\n - Dam\n - Weir\n - Lock\n - Ford\n - Dyke\n maxScale: 50000.0\n minScale: 1.0\n name: HY.PhysicalWaters.ManMadeObject\n sourceMetadataIdentifier: 07575774-57a1-4419-bab4-6c88fdeb02b2\n styles:\n - name: HY.PhysicalWaters.ManMadeObject.Default\n title: Man-made objects default style\n title: Man-made Object\n visible: true\n - abstract: Crossing line, crossing point, dam or weir, sluice, embankment, lock.\n data:\n gpkg:\n blobKey: geopackages/hwh/hydrografie/aaa/1/Man-madeObject.gpkg\n columns:\n - gml_id\n - beginlifespanversion\n - condition\n - endlifespanversion\n - localid\n - name\n - namespace\n geometryType: Point\n table: lock\n datasetMetadataIdentifier: 07575774-57a1-4419-bab4-6c88fdeb02b2\n group: HY.PhysicalWaters.ManMadeObject\n keywords:\n - Man Made\n - Duikersifonhevel\n - Aquaduct\n - Brug\n - Stuw\n - Vastedam\n - Waterkering\n - Sluis.\n name: HY.PhysicalWaters.ManMadeObject.lock\n sourceMetadataIdentifier: 07575774-57a1-4419-bab4-6c88fdeb02b2\n styles:\n - name: HY.PhysicalWaters.ManMadeObject.Default\n title: Lock\n visualization: lock.style\n title: Man-made Object\n maxScale: 50000.0\n minScale: 1.0\n visible: false\n - abstract: Crossing line, crossing point, dam or weir, sluice, embankment, lock.\n data:\n gpkg:\n blobKey: geopackages/hwh/hydrografie/aaa/1/Man-madeObject.gpkg\n columns:\n - gml_id\n - beginlifespanversion\n - condition\n - endlifespanversion\n - localid\n - name\n - namespace\n - type\n geometryType: Point\n table: crossingpoint\n datasetMetadataIdentifier: 07575774-57a1-4419-bab4-6c88fdeb02b2\n group: HY.PhysicalWaters.ManMadeObject\n keywords:\n - Man Made\n - Duikersifonhevel\n - Aquaduct\n - Brug\n - Stuw\n - Vastedam\n - Waterkering\n - Sluis.\n name: HY.PhysicalWaters.ManMadeObject.crossingpoint\n sourceMetadataIdentifier: 07575774-57a1-4419-bab4-6c88fdeb02b2\n styles:\n - name: HY.PhysicalWaters.ManMadeObject.Default\n title: Crossing Point\n visualization: crossingpoint.style\n title: Man-made Object\n maxScale: 50000.0\n minScale: 1.0\n visible: false\n - abstract: Crossing line, crossing point, dam or weir, sluice, embankment, lock.\n data:\n gpkg:\n blobKey: geopackages/hwh/hydrografie/aaa/1/Man-madeObject.gpkg\n columns:\n - gml_id\n - beginlifespanversion\n - condition\n - endlifespanversion\n - localid\n - name\n - namespace\n geometryType: Point\n table: sluice\n datasetMetadataIdentifier: 07575774-57a1-4419-bab4-6c88fdeb02b2\n group: HY.PhysicalWaters.ManMadeObject\n keywords:\n - Man Made\n - Duikersifonhevel\n - Aquaduct\n - Brug\n - Stuw\n - Vastedam\n - Waterkering\n - Sluis.\n name: HY.PhysicalWaters.ManMadeObject.sluice\n sourceMetadataIdentifier: 07575774-57a1-4419-bab4-6c88fdeb02b2\n styles:\n - name: HY.PhysicalWaters.ManMadeObject.Default\n title: Sluice\n visualization: sluice.style\n title: Man-made Object\n maxScale: 50000.0\n minScale: 1.0\n visible: false\n - abstract: Crossing line, crossing point, dam or weir, sluice, embankment, lock.\n data:\n gpkg:\n blobKey: geopackages/hwh/hydrografie/aaa/1/Man-madeObject.gpkg\n columns:\n - gml_id\n - beginlifespanversion\n - condition\n - endlifespanversion\n - localid\n - name\n - namespace\n geometryType: MultiLineString\n table: embankment\n datasetMetadataIdentifier: 07575774-57a1-4419-bab4-6c88fdeb02b2\n group: HY.PhysicalWaters.ManMadeObject\n keywords:\n - Man Made\n - Duikersifonhevel\n - Aquaduct\n - Brug\n - Stuw\n - Vastedam\n - Waterkering\n - Sluis.\n name: HY.PhysicalWaters.ManMadeObject.embankment\n sourceMetadataIdentifier: 07575774-57a1-4419-bab4-6c88fdeb02b2\n styles:\n - name: HY.PhysicalWaters.ManMadeObject.Default\n title: Embankment\n visualization: embankment.style\n title: Man-made Object\n maxScale: 50000.0\n minScale: 1.0\n visible: false\n - abstract: Crossing line, crossing point, dam or weir, sluice, embankment, lock.\n data:\n gpkg:\n blobKey: geopackages/hwh/hydrografie/aaa/1/Man-madeObject.gpkg\n columns:\n - gml_id\n - beginlifespanversion\n - condition\n - endlifespanversion\n - localid\n - name\n - namespace\n - type\n geometryType: MultiLineString\n table: crossingline\n datasetMetadataIdentifier: 07575774-57a1-4419-bab4-6c88fdeb02b2\n group: HY.PhysicalWaters.ManMadeObject\n keywords:\n - Man Made\n - Duikersifonhevel\n - Aquaduct\n - Brug\n - Stuw\n - Vastedam\n - Waterkering\n - Sluis.\n name: HY.PhysicalWaters.ManMadeObject.crossingline\n sourceMetadataIdentifier: 07575774-57a1-4419-bab4-6c88fdeb02b2\n styles:\n - name: HY.PhysicalWaters.ManMadeObject.Default\n title: Crossing Line\n visualization: crossingline.style\n title: Man-made Object\n maxScale: 50000.0\n minScale: 1.0\n visible: false\n - abstract: Crossing line, crossing point, dam or weir, sluice, embankment, lock.\n data:\n gpkg:\n blobKey: geopackages/hwh/hydrografie/aaa/1/Man-madeObject.gpkg\n columns:\n - gml_id\n - beginlifespanversion\n - condition\n - endlifespanversion\n - localid\n - name\n - namespace\n geometryType: Point\n table: damorweir\n datasetMetadataIdentifier: 07575774-57a1-4419-bab4-6c88fdeb02b2\n group: HY.PhysicalWaters.ManMadeObject\n keywords:\n - Man Made\n - Duikersifonhevel\n - Aquaduct\n - Brug\n - Stuw\n - Vastedam\n - Waterkering\n - Sluis.\n name: HY.PhysicalWaters.ManMadeObject.damorweir\n sourceMetadataIdentifier: 07575774-57a1-4419-bab4-6c88fdeb02b2\n styles:\n - name: HY.PhysicalWaters.ManMadeObject.Default\n title: Dam or Weir\n visualization: damorweir.style\n title: Man-made Object\n maxScale: 50000.0\n minScale: 1.0\n visible: false\n" var v2wms v2beta1.WMS err := yaml.Unmarshal([]byte(v2wmsstring), &v2wms) @@ -294,10 +300,11 @@ func TestGetConfigForWMSWithGroupLayers(t *testing.T) { func TestGetConfigForWMSWithGroupLayersAndTopGroupLayer(t *testing.T) { ownerInfo := &smoothoperatorv1.OwnerInfo{ Spec: smoothoperatorv1.OwnerInfoSpec{ - NamespaceTemplate: "http://{{prefix}}.geonovum.nl", + NamespaceTemplate: smoothoperatorutils.Pointer("http://{{prefix}}.geonovum.nl"), }, } + //nolint:misspell v2wmsstring := "apiVersion: pdok.nl/v2beta1\nkind: WMS\nmetadata:\n name: kadaster-kadastralekaart\n labels:\n dataset-owner: kadaster\n dataset: kadastralekaart\n service-version: v5_0\n service-type: wms\nspec:\n general:\n datasetOwner: kadaster\n dataset: kadastralekaart\n serviceVersion: v5_0\n kubernetes:\n healthCheck:\n querystring: language=dut&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX=193882.0336615453998,470528.1693874415942,193922.4213813782844,470564.250484353397&CRS=EPSG:28992&WIDTH=769&HEIGHT=687&LAYERS=OpenbareRuimteNaam,Bebouwing,Perceel,KadastraleGrens&FORMAT=image/png&DPI=96&MAP_RESOLUTION=96&FORMAT_OPTIONS=dpi:96&TRANSPARENT=TRUE\n mimetype: image/png\n resources:\n limits:\n memory: \"103M\"\n ephemeralStorage: \"104M\"\n requests:\n cpu: \"1001\"\n memory: \"101M\"\n ephemeralStorage: \"102M\"\n options:\n automaticCasing: true\n disableWebserviceProxy: false\n includeIngress: true\n validateRequests: true\n rewriteGroupToDataLayers: true\n service:\n inspire: false\n title: Kadastrale Kaart (WMS)\n abstract: Overzicht van de ligging van de kadastrale percelen in Nederland. Fungeert als schakel tussen terrein en registratie, vervult voor externe gebruiker vaak een referentiefunctie, een ondergrond ten opzichte waarvan de gebruiker eigen informatie kan vastleggen en presenteren.\n keywords:\n - Kadaster\n - Kadastrale percelen\n - Kadastrale grens\n - Kadastrale kaart\n - Bebouwing\n - Nummeraanduidingreeks\n - Openbare ruimte naam\n - Perceel\n - Grens\n - Kwaliteit\n - Kwaliteitslabels\n - HVD\n - Geospatiale data\n metadataIdentifier: 97cf6a64-9cfc-4ce6-9741-2db44fd27fca\n authority:\n name: kadaster\n url: https://www.kadaster.nl\n dataEPSG: EPSG:28992\n resolution: 91\n defResolution: 91\n extent: \"-25000 250000 280000 860000\"\n maxSize: 10000\n stylingAssets:\n configMapRefs:\n - name: includes\n blobKeys:\n - resources/fonts/liberation-sans.ttf\n - resources/fonts/liberation-sans-italic.ttf\n layers:\n - name: Kadastralekaart\n title: KadastraleKaartv5\n abstract: Overzicht van de ligging van de kadastrale percelen in Nederland. Fungeert als schakel tussen terrein en registratie, vervult voor externe gebruiker vaak een referentiefunctie, een ondergrond ten opzichte waarvan de gebruiker eigen informatie kan vastleggen en presenteren.\n maxScale: 6001\n keywords:\n - Kadaster\n - Kadastrale percelen\n - Kadastrale grens\n datasetMetadataIdentifier: a29917b9-3426-4041-a11b-69bcb2256904\n sourceMetadataIdentifier: 06b6c650-cdb1-11dd-ad8b-0800200c9a64\n styles:\n - name: standaard\n title: Standaardvisualisatie\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n - name: kwaliteit\n title: Kwaliteitsvisualisatie\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n - name: print\n title: Printvisualisatie\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n - name: Bebouwing\n visible: true\n group: Kadastralekaart\n title: Bebouwing\n abstract: De laag Bebouwing is een selectie op panden van de BGT.\n keywords:\n - Bebouwing\n datasetMetadataIdentifier: a29917b9-3426-4041-a11b-69bcb2256904\n sourceMetadataIdentifier: 06b6c650-cdb1-11dd-ad8b-0800200c9a64\n minScale: 50\n maxScale: 6001\n styles:\n - name: standaard:bebouwing\n title: Standaardvisualisatie Bebouwing\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n - name: kwaliteit:bebouwing\n title: Kwaliteitsvisualisatie Bebouwing\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n - name: print:bebouwing\n title: Printvisualisatie Bebouwing\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n - name: Bebouwingvlak\n visible: true\n group: Bebouwing\n title: Bebouwingvlak\n abstract: De laag Bebouwing is een selectie op panden van de BGT.\n keywords:\n - Bebouwing\n datasetMetadataIdentifier: a29917b9-3426-4041-a11b-69bcb2256904\n sourceMetadataIdentifier: 06b6c650-cdb1-11dd-ad8b-0800200c9a64\n minScale: 50\n maxScale: 6001\n styles:\n - name: standaard\n title: Standaardvisualisatie\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n visualization: bebouwing.style\n - name: kwaliteit\n title: Kwaliteitsvisualisatie\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: bebouwing_kwaliteit.style\n - name: print\n title: Printvisualisatie\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: bebouwing_print.style\n - name: standaard:bebouwing\n title: Standaardvisualisatie Bebouwing\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n visualization: bebouwing.group.style\n - name: kwaliteit:bebouwing\n title: Kwaliteitsvisualisatie Bebouwing\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: bebouwing_kwaliteit.group.style\n - name: print:bebouwing\n title: Printvisualisatie Bebouwing\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: bebouwing_print.group.style\n data:\n gpkg:\n blobKey: geopackages/kadaster/kadastralekaart_brk/aaa/1/pand.gpkg\n table: pand\n geometryType: Polygon\n columns:\n - object_begin_tijd\n - lv_publicatiedatum\n - relatieve_hoogteligging\n - in_onderzoek\n - tijdstip_registratie\n - identificatie_namespace\n - identificatie_lokaal_id\n - bronhouder\n - bgt_status\n - plus_status\n - identificatie_bag_pnd\n aliases:\n lv_publicatiedatum: LV-publicatiedatum\n identificatie_lokaal_id: identificatieLokaalID\n identificatie_bag_pnd: identificatieBAGPND\n bgt_status: bgt-status\n plus_status: plus-status\n - name: Nummeraanduidingreeks\n visible: true\n group: Bebouwing\n title: Nummeraanduidingreeks\n abstract: De laag Bebouwing is een selectie op panden van de BGT.\n keywords:\n - Nummeraanduidingreeks\n datasetMetadataIdentifier: a29917b9-3426-4041-a11b-69bcb2256904\n sourceMetadataIdentifier: 06b6c650-cdb1-11dd-ad8b-0800200c9a64\n minScale: 50\n maxScale: 2001\n styles:\n - name: standaard\n title: Standaardvisualisatie\n abstract: Standaarvisualisatie van de nummeraanduidingreeks.\n visualization: nummeraanduidingreeks.style\n - name: kwaliteit\n title: Kwaliteitsvisualisatie\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: nummeraanduidingreeks_kwaliteit.style\n - name: print\n title: Printvisualisatie\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: nummeraanduidingreeks_print.style\n - name: standaard:bebouwing\n title: Standaardvisualisatie Bebouwing\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n visualization: nummeraanduidingreeks.group.style\n - name: kwaliteit:bebouwing\n title: Kwaliteitsvisualisatie Bebouwing\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: nummeraanduidingreeks_kwaliteit.group.style\n - name: print:bebouwing\n title: Printvisualisatie Bebouwing\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: nummeraanduidingreeks_print.group.style\n data:\n gpkg:\n blobKey: geopackages/kadaster/kadastralekaart_brk/aaa/1/pand_nummeraanduiding.gpkg\n table: pand_nummeraanduiding\n geometryType: Point\n columns:\n - bebouwing_id\n - hoek\n - tekst\n - bag_vbo_laagste_huisnummer\n - bag_vbo_hoogste_huisnummer\n - hoek\n aliases:\n bebouwing_id: bebouwingID\n bag_vbo_laagste_huisnummer: identificatie_BAGVBOLaagsteHuisnummer\n bag_vbo_hoogste_huisnummer: identificatie_BAGVBOHoogsteHuisnummer\n - name: OpenbareRuimteNaam\n visible: true\n group: Kadastralekaart\n title: OpenbareRuimteNaam\n abstract: De laag Openbareruimtenaam is een selectie op de openbare ruimte labels van de BGT met een bgt-status \"bestaand\" die een classificatie (openbareruimtetype) Weg en Water hebben.\n keywords:\n - Openbare ruimte naam\n datasetMetadataIdentifier: a29917b9-3426-4041-a11b-69bcb2256904\n sourceMetadataIdentifier: 06b6c650-cdb1-11dd-ad8b-0800200c9a64\n minScale: 50\n maxScale: 2001\n styles:\n - name: standaard\n title: Standaardvisualisatie\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n visualization: openbareruimtenaam.style\n - name: kwaliteit\n title: Kwaliteitsvisualisatie\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: openbareruimtenaam_kwaliteit.style\n - name: print\n title: Printvisualisatie\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: openbareruimtenaam_print.style\n - name: standaard:openbareruimtenaam\n title: Standaardvisualisatie OpenbareRuimteNaam\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n visualization: openbareruimtenaam.group.style\n - name: kwaliteit:openbareruimtenaam\n title: Kwaliteitsvisualisatie OpenbareRuimteNaam\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: openbareruimtenaam_kwaliteit.group.style\n - name: print:openbareruimtenaam\n title: Printvisualisatie OpenbareRuimteNaam\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: openbareruimtenaam_print.group.style\n data:\n gpkg:\n blobKey: geopackages/kadaster/kadastralekaart_brk/aaa/1/openbareruimtelabel.gpkg\n table: openbareruimtelabel\n geometryType: Point\n columns:\n - object_begin_tijd\n - lv_publicatiedatum\n - relatieve_hoogteligging\n - in_onderzoek\n - tijdstip_registratie\n - identificatie_namespace\n - identificatie_lokaal_id\n - bronhouder\n - bgt_status\n - plus_status\n - identificatie_bag_opr\n - tekst\n - hoek\n - openbare_ruimte_type\n aliases:\n lv_publicatiedatum: LV-publicatiedatum\n identificatie_lokaal_id: identificatieLokaalID\n identificatie_bag_opr: identificatieBAGOPR\n bgt_status: bgt-status\n plus_status: plus-status\n - name: Perceel\n visible: true\n group: Kadastralekaart\n title: Perceel\n abstract: Een perceel is een stuk grond waarvan het Kadaster de grenzen heeft gemeten of gaat meten en dat bij het Kadaster een eigen nummer heeft. Een perceel is een begrensd deel van het Nederlands grondgebied dat kadastraal geïdentificeerd is en met kadastrale grenzen begrensd is.\n keywords:\n - Perceel\n - Kadastrale percelen\n datasetMetadataIdentifier: a29917b9-3426-4041-a11b-69bcb2256904\n sourceMetadataIdentifier: 06b6c650-cdb1-11dd-ad8b-0800200c9a64\n minScale: 50\n maxScale: 6001\n styles:\n - name: standaard:perceel\n title: Standaardvisualisatie Perceel\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n - name: kwaliteit:perceel\n title: Kwaliteitsvisualisatie Perceel\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n - name: print:perceel\n title: Printvisualisatie Perceel\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n - name: Perceelvlak\n visible: true\n group: Perceel\n title: Perceelvlak\n abstract: Een perceel is een stuk grond waarvan het Kadaster de grenzen heeft gemeten of gaat meten en dat bij het Kadaster een eigen nummer heeft. Een perceel is een begrensd deel van het Nederlands grondgebied dat kadastraal geïdentificeerd is en met kadastrale grenzen begrensd is.\n keywords:\n - Kadastrale percelen\n datasetMetadataIdentifier: a29917b9-3426-4041-a11b-69bcb2256904\n sourceMetadataIdentifier: 06b6c650-cdb1-11dd-ad8b-0800200c9a64\n minScale: 50\n maxScale: 6001\n styles:\n - name: standaard\n title: Standaardvisualisatie\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n visualization: perceelvlak.style\n - name: kwaliteit\n title: Kwaliteitsvisualisatie\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: perceelvlak_kwaliteit.style\n - name: print\n title: Printvisualisatie\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: perceelvlak_print.style\n - name: standaard:perceel\n title: Standaardvisualisatie Perceel\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n visualization: perceelvlak.group.style\n - name: kwaliteit:perceel\n title: Kwaliteitsvisualisatie Perceel\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: perceelvlak_kwaliteit.group.style\n - name: print:perceel\n title: Printvisualisatie Perceel\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: perceelvlak_print.group.style\n data:\n gpkg:\n blobKey: geopackages/kadaster/kadastralekaart_brk/aaa/1/perceel.gpkg\n table: perceel\n geometryType: Polygon\n columns:\n - identificatie_namespace\n - identificatie_lokaal_id\n - begin_geldigheid\n - tijdstip_registratie\n - volgnummer\n - status_historie_code\n - status_historie_waarde\n - kadastrale_gemeente_code\n - kadastrale_gemeente_waarde\n - sectie\n - akr_kadastrale_gemeente_code_code\n - akr_kadastrale_gemeente_code_waarde\n - kadastrale_grootte_waarde\n - soort_grootte_code\n - soort_grootte_waarde\n - perceelnummer\n - perceelnummer_rotatie\n - perceelnummer_verschuiving_delta_x\n - perceelnummer_verschuiving_delta_y\n - perceelnummer_plaatscoordinaat_x\n - perceelnummer_plaatscoordinaat_y\n aliases:\n identificatie_lokaal_id: identificatieLokaalID\n akr_kadastrale_gemeente_code_code: AKRKadastraleGemeenteCodeCode\n akr_kadastrale_gemeente_code_waarde: AKRKadastraleGemeenteCodeWaarde\n - name: Label\n visible: true\n group: Perceel\n title: Label\n abstract: Een perceel is een stuk grond waarvan het Kadaster de grenzen heeft gemeten of gaat meten en dat bij het Kadaster een eigen nummer heeft. Een perceel is een begrensd deel van het Nederlands grondgebied dat kadastraal geïdentificeerd is en met kadastrale grenzen begrensd is.\n keywords:\n - Kadastrale percelen\n datasetMetadataIdentifier: a29917b9-3426-4041-a11b-69bcb2256904\n sourceMetadataIdentifier: 06b6c650-cdb1-11dd-ad8b-0800200c9a64\n minScale: 50\n maxScale: 6001\n styles:\n - name: standaard\n title: Standaardvisualisatie\n abstract: Standaarvisualisatie van het label.\n visualization: label.style\n - name: standaard:perceel\n title: Standaardvisualisatie Perceel\n abstract: Standaarvisualisatie van het label.\n visualization: label.group.style\n - name: kwaliteit\n title: Kwaliteitsvisualisatie\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: label_kwaliteit.style\n - name: kwaliteit:perceel\n title: Kwaliteitsvisualisatie Perceel\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: label_kwaliteit.group.style\n - name: print\n title: Printvisualisatie\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: label_print.style\n - name: print:perceel\n title: Printvisualisatie Perceel\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: label_print.group.style\n data:\n gpkg:\n blobKey: geopackages/kadaster/kadastralekaart_brk/aaa/1/perceel_label.gpkg\n table: perceel_label\n geometryType: Point\n columns:\n - perceel_id\n - perceelnummer\n - rotatie\n - verschuiving_delta_x\n - verschuiving_delta_y\n aliases:\n perceel_id: perceelID\n - name: Bijpijling\n visible: true\n group: Perceel\n title: Bijpijling\n abstract: Een perceel is een stuk grond waarvan het Kadaster de grenzen heeft gemeten of gaat meten en dat bij het Kadaster een eigen nummer heeft. Een perceel is een begrensd deel van het Nederlands grondgebied dat kadastraal geïdentificeerd is en met kadastrale grenzen begrensd is.\n keywords:\n - Kadastrale percelen\n datasetMetadataIdentifier: a29917b9-3426-4041-a11b-69bcb2256904\n sourceMetadataIdentifier: 06b6c650-cdb1-11dd-ad8b-0800200c9a64\n minScale: 50\n maxScale: 6001\n styles:\n - name: standaard\n title: Standaardvisualisatie\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n visualization: bijpijling.style\n - name: kwaliteit\n title: Kwaliteitsvisualisatie\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: bijpijling_kwaliteit.style\n - name: print\n title: Printvisualisatie\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: bijpijling_print.style\n - name: standaard:perceel\n title: Standaardvisualisatie Perceel\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n visualization: bijpijling.group.style\n - name: kwaliteit:perceel\n title: Kwaliteitsvisualisatie Perceel\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: bijpijling_kwaliteit.group.style\n - name: print:perceel\n title: Printvisualisatie Perceel\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: bijpijling_print.group.style\n data:\n gpkg:\n blobKey: geopackages/kadaster/kadastralekaart_brk/aaa/1/perceel_bijpijling.gpkg\n table: perceel_bijpijling\n geometryType: LineString\n columns:\n - perceel_id\n aliases:\n perceel_id: perceelID\n - name: KadastraleGrens\n visible: true\n group: Kadastralekaart\n title: KadastraleGrens\n abstract: Een Kadastrale Grens is de weergave van een grens op de kadastrale kaart die door de dienst van het Kadaster tussen percelen (voorlopig) vastgesteld wordt, op basis van inlichtingen van belanghebbenden en met gebruikmaking van de aan de kadastrale kaart ten grondslag liggende bescheiden die in elk geval de landmeetkundige gegevens bevatten van hetgeen op die kaart wordt weergegeven.\n keywords:\n - Grens\n - Kadastrale grenzen\n datasetMetadataIdentifier: a29917b9-3426-4041-a11b-69bcb2256904\n sourceMetadataIdentifier: 06b6c650-cdb1-11dd-ad8b-0800200c9a64\n minScale: 50\n maxScale: 6001\n styles:\n - name: standaard\n title: Standaardvisualisatie\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n visualization: kadastralegrens.style\n - name: kwaliteit\n title: Kwaliteitsvisualisatie\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: kadastralegrens_kwaliteit.style\n - name: print\n title: Printvisualisatie\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: kadastralegrens_print.style\n - name: standaard:kadastralegrens\n title: Standaardvisualisatie KadastraleGrens\n abstract: Standaardvisualisatie met grenzen op basis van type (definitief, voorlopig of administratief).\n visualization: kadastralegrens.group.style\n - name: kwaliteit:kadastralegrens\n title: Kwaliteitsvisualisatie KadastraleGrens\n abstract: Kwaliteitsvisualisatie met grenzen op basis van kwaliteitsklasse (B, C, D of E).\n visualization: kadastralegrens_kwaliteit.group.style\n - name: print:kadastralegrens\n title: Printvisualisatie KadastraleGrens\n abstract: Visualisatie ten behoeve van afdrukken op 180 dpi.\n visualization: kadastralegrens_print.group.style\n data:\n gpkg:\n blobKey: geopackages/kadaster/kadastralekaart_brk/aaa/1/kadastrale_grens.gpkg\n table: kadastrale_grens\n geometryType: LineString\n columns:\n - begin_geldigheid\n - tijdstip_registratie\n - volgnummer\n - status_historie_code\n - status_historie_waarde\n - identificatie_namespace\n - identificatie_lokaal_id\n - type_grens_code\n - type_grens_waarde\n - classificatie_kwaliteit_code\n - classificatie_kwaliteit_waarde\n - perceel_links_identificatie_namespace\n - perceel_links_identificatie_lokaal_id\n - perceel_rechts_identificatie_namespace\n - perceel_rechts_identificatie_lokaal_id\n aliases:\n identificatie_lokaal_id: identificatieLokaalID\n perceel_links_identificatie_lokaal_id: perceelLinksIdentificatieLokaalID\n perceel_rechts_identificatie_lokaal_id: perceelRechtsIdentificatieLokaalID\n classificatie_kwaliteit_code: ClassificatieKwaliteitCode\n classificatie_kwaliteit_waarde: ClassificatieKwaliteitWaarde\n" var v2wms v2beta1.WMS err := yaml.Unmarshal([]byte(v2wmsstring), &v2wms) @@ -319,7 +326,7 @@ func TestGetConfigForWMSWithGroupLayersAndTopGroupLayer(t *testing.T) { func TestGetConfigForTifWMS(t *testing.T) { ownerInfo := &smoothoperatorv1.OwnerInfo{ Spec: smoothoperatorv1.OwnerInfoSpec{ - NamespaceTemplate: "http://{{prefix}}.geonovum.nl", + NamespaceTemplate: smoothoperatorutils.Pointer("http://{{prefix}}.geonovum.nl"), }, } @@ -344,7 +351,7 @@ func TestGetConfigForTifWMS(t *testing.T) { func TestGetConfigForPostgisWMS(t *testing.T) { ownerInfo := &smoothoperatorv1.OwnerInfo{ Spec: smoothoperatorv1.OwnerInfoSpec{ - NamespaceTemplate: "http://{{prefix}}.geonovum.nl", + NamespaceTemplate: smoothoperatorutils.Pointer("http://{{prefix}}.geonovum.nl"), }, } diff --git a/internal/controller/mapfilegenerator/mapper.go b/internal/controller/mapfilegenerator/mapper.go index 0bd98a6..3d6b91a 100644 --- a/internal/controller/mapfilegenerator/mapper.go +++ b/internal/controller/mapfilegenerator/mapper.go @@ -17,22 +17,44 @@ const ( geopackagePath = "/srv/data/gpkg" ) +var mapserverDebugLevel = 0 + +var defaultEpsgList = []string{ + "EPSG:28992", + "EPSG:25831", + "EPSG:25832", + "EPSG:3034", + "EPSG:3035", + "EPSG:3857", + "EPSG:4258", + "EPSG:4326", +} + +func SetDebugLevel(level int) { + if level < 0 || level > 5 { + panic("level must be between 0 and 5") + } + + mapserverDebugLevel = level +} + func MapWFSToMapfileGeneratorInput(wfs *pdoknlv3.WFS, ownerInfo *smoothoperatorv1.OwnerInfo) (WFSInput, error) { input := WFSInput{ BaseServiceInput: BaseServiceInput{ Title: mapperutils.EscapeQuotes(wfs.Spec.Service.Title), Abstract: mapperutils.EscapeQuotes(wfs.Spec.Service.Abstract), Keywords: strings.Join(wfs.Spec.Service.Keywords, ","), - OnlineResource: pdoknlv3.GetHost(), + OnlineResource: pdoknlv3.GetHost(true), Path: mapperutils.GetPath(wfs), - MetadataId: wfs.Spec.Service.Inspire.ServiceMetadataURL.CSW.MetadataIdentifier, + MetadataID: wfs.Spec.Service.Inspire.ServiceMetadataURL.CSW.MetadataIdentifier, Extent: wfs.Spec.Service.Bbox.DefaultCRS.ToExtent(), NamespacePrefix: wfs.Spec.Service.Prefix, NamespaceURI: mapperutils.GetNamespaceURI(wfs.Spec.Service.Prefix, ownerInfo), AutomaticCasing: wfs.Spec.Options.AutomaticCasing, DataEPSG: wfs.Spec.Service.DefaultCrs, // TODO Should this be a constant like in v2, or OtherCRS + default - EPSGList: wfs.Spec.Service.OtherCrs, + EPSGList: defaultEpsgList, // wfs.Spec.Service.OtherCrs, + DebugLevel: mapserverDebugLevel, }, MaxFeatures: smoothoperatorutils.PointerVal(wfs.Spec.Service.CountDefault, strconv.Itoa(defaultMaxFeatures)), Layers: getWFSLayers(wfs.Spec.Service.FeatureTypes), @@ -54,7 +76,7 @@ func getWFSLayers(featureTypes []pdoknlv3.FeatureType) (layers []WFSLayer) { Abstract: mapperutils.EscapeQuotes(featureType.Abstract), Keywords: strings.Join(featureType.Keywords, ","), Extent: bbox.DefaultCRS.ToExtent(), - MetadataId: featureType.DatasetMetadataURL.CSW.MetadataIdentifier, + MetadataID: featureType.DatasetMetadataURL.CSW.MetadataIdentifier, Columns: getColumns(featureType.Data), TableName: featureType.Data.GetTableName(), GeometryType: featureType.Data.GetGeometryType(), @@ -92,7 +114,7 @@ func getGeopackagePath(data pdoknlv3.Data) *string { return smoothoperatorutils.Pointer(geopackagePath + "/" + blobName) } -func MapWMSToMapfileGeneratorInput(wms *pdoknlv3.WMS, ownerInfo *smoothoperatorv1.OwnerInfo) (WMSInput, error) { +func MapWMSToMapfileGeneratorInput(wms *pdoknlv3.WMS, _ *smoothoperatorv1.OwnerInfo) (WMSInput, error) { service := wms.Spec.Service accessConstraints := service.AccessConstraints @@ -110,9 +132,9 @@ func MapWMSToMapfileGeneratorInput(wms *pdoknlv3.WMS, ownerInfo *smoothoperatorv datasetName := wms.ObjectMeta.Labels["dataset"] protocol := "http" authority := wms.GetAuthority() - authorityUrl := "" + authorityURL := "" if authority != nil { - authorityUrl = authority.URL + authorityURL = authority.URL } box := service.GetBoundingBox() @@ -125,11 +147,11 @@ func MapWMSToMapfileGeneratorInput(wms *pdoknlv3.WMS, ownerInfo *smoothoperatorv maxSize = strconv.Itoa(int(*service.MaxSize)) } - metadataId := "" + var metadataID string if service.Inspire != nil { - metadataId = service.Inspire.ServiceMetadataURL.CSW.MetadataIdentifier + metadataID = service.Inspire.ServiceMetadataURL.CSW.MetadataIdentifier } else { - metadataId = wms.ObjectMeta.Annotations[v2beta1.SERVICE_METADATA_IDENTIFIER_ANNOTATION] + metadataID = wms.ObjectMeta.Annotations[v2beta1.ServiceMetatdataIdentifierAnnotation] } var fonts *string @@ -152,11 +174,11 @@ func MapWMSToMapfileGeneratorInput(wms *pdoknlv3.WMS, ownerInfo *smoothoperatorv Extent: extent, NamespacePrefix: datasetName, NamespaceURI: fmt.Sprintf("%s://%s.geonovum.nl", protocol, datasetName), - OnlineResource: pdoknlv3.GetHost(), + OnlineResource: pdoknlv3.GetHost(true), Path: mapperutils.GetPath(wms), - MetadataId: metadataId, + MetadataID: metadataID, DatasetOwner: &datasetOwner, - AuthorityURL: &authorityUrl, + AuthorityURL: &authorityURL, AutomaticCasing: wms.Spec.Options.AutomaticCasing, DataEPSG: service.DataEPSG, EPSGList: epsgs, @@ -214,6 +236,11 @@ func getWMSLayer(serviceLayer pdoknlv3.Layer, serviceExtent string, wms *pdoknlv tableName = serviceLayer.Data.GetTableName() } + metadataID := "" + if serviceLayer.DatasetMetadataURL != nil && serviceLayer.DatasetMetadataURL.CSW != nil { + metadataID = serviceLayer.DatasetMetadataURL.CSW.MetadataIdentifier + } + result := WMSLayer{ BaseLayer: BaseLayer{ Name: *serviceLayer.Name, @@ -221,7 +248,7 @@ func getWMSLayer(serviceLayer pdoknlv3.Layer, serviceExtent string, wms *pdoknlv Abstract: smoothoperatorutils.PointerVal(serviceLayer.Abstract, ""), Keywords: strings.Join(serviceLayer.Keywords, ","), Extent: layerExtent, - MetadataId: serviceLayer.DatasetMetadataURL.CSW.MetadataIdentifier, + MetadataID: metadataID, Columns: columns, GeometryType: nil, GeopackagePath: nil, @@ -243,7 +270,8 @@ func getWMSLayer(serviceLayer pdoknlv3.Layer, serviceExtent string, wms *pdoknlv } if serviceLayer.Data != nil { - if serviceLayer.Data.Gpkg != nil { + switch { + case serviceLayer.Data.Gpkg != nil: gpkg := serviceLayer.Data.Gpkg result.GeometryType = &gpkg.GeometryType @@ -256,11 +284,11 @@ func getWMSLayer(serviceLayer pdoknlv3.Layer, serviceExtent string, wms *pdoknlv } result.GeopackagePath = &geopackageConstructedPath - } else if serviceLayer.Data.TIF != nil { + case serviceLayer.Data.TIF != nil: tif := serviceLayer.Data.TIF result.GeometryType = smoothoperatorutils.Pointer("Raster") result.Offsite = smoothoperatorutils.PointerVal(tif.Offsite, "") - } else if serviceLayer.Data.Postgis != nil { + case serviceLayer.Data.Postgis != nil: postgis := serviceLayer.Data.Postgis result.Postgis = smoothoperatorutils.Pointer(true) result.GeometryType = &postgis.GeometryType diff --git a/internal/controller/mapfilegenerator/types.go b/internal/controller/mapfilegenerator/types.go index 01ba547..911fc45 100644 --- a/internal/controller/mapfilegenerator/types.go +++ b/internal/controller/mapfilegenerator/types.go @@ -10,12 +10,13 @@ type BaseServiceInput struct { NamespaceURI string `json:"service_namespace_uri"` OnlineResource string `json:"service_onlineresource"` Path string `json:"service_path"` - MetadataId string `json:"service_metadata_id"` + MetadataID string `json:"service_metadata_id"` DatasetOwner *string `json:"dataset_owner,omitempty"` AuthorityURL *string `json:"authority_url,omitempty"` AutomaticCasing bool `json:"automatic_casing"` DataEPSG string `json:"data_epsg"` EPSGList []string `json:"epsg_list"` + DebugLevel int `json:"service_debug_level"` } //nolint:tagliatelle @@ -46,7 +47,7 @@ type BaseLayer struct { Abstract string `json:"abstract"` Keywords string `json:"keywords"` Extent string `json:"layer_extent"` - MetadataId string `json:"dataset_metadata_id"` + MetadataID string `json:"dataset_metadata_id"` Columns []Column `json:"columns"` GeometryType *string `json:"geometry_type,omitempty"` GeopackagePath *string `json:"gpkg_path,omitempty"` @@ -66,6 +67,7 @@ type GroupLayer struct { StyleTitle string `json:"styleTitle"` } +//nolint:tagliatelle type WMSLayer struct { BaseLayer GroupName string `json:"group_name,omitempty"` diff --git a/internal/controller/mapperutils/utils.go b/internal/controller/mapperutils/utils.go index cf0e1fb..bc8d624 100644 --- a/internal/controller/mapperutils/utils.go +++ b/internal/controller/mapperutils/utils.go @@ -44,7 +44,7 @@ func ephemeralStorage[O pdoknlv3.WMSWFS](obj O, limit bool) *resource.Quantity { } func GetNamespaceURI(prefix string, ownerInfo *smoothoperatorv1.OwnerInfo) string { - return strings.ReplaceAll(ownerInfo.Spec.NamespaceTemplate, "{{prefix}}", prefix) + return strings.ReplaceAll(*ownerInfo.Spec.NamespaceTemplate, "{{prefix}}", prefix) } func EscapeQuotes(s string) string { diff --git a/internal/controller/mapserver/deployment.go b/internal/controller/mapserver/deployment.go index 61ff318..e74811f 100644 --- a/internal/controller/mapserver/deployment.go +++ b/internal/controller/mapserver/deployment.go @@ -24,6 +24,8 @@ const ( ConfigMapFeatureinfoGeneratorVolumeName = "featureinfo-generator-config" // TODO How should we determine this boundingbox? healthCheckBbox = "190061.4619730016857,462435.5987861062749,202917.7508707302331,473761.6884966178914" + + mimeTextXML = "text/xml" ) func GetVolumesForDeployment[O pdoknlv3.WMSWFS](obj O, configMapNames types.HashedConfigMapNames) []v1.Volume { @@ -51,6 +53,17 @@ func GetVolumesForDeployment[O pdoknlv3.WMSWFS](obj O, configMapNames types.Hash } } + newVolumeSource := func(name string) v1.VolumeSource { + return v1.VolumeSource{ + ConfigMap: &v1.ConfigMapVolumeSource{ + DefaultMode: smoothoperatorutils.Pointer(int32(0644)), + LocalObjectReference: v1.LocalObjectReference{ + Name: name, + }, + }, + } + } + volumes := []v1.Volume{ baseVolume, { @@ -60,86 +73,51 @@ func GetVolumesForDeployment[O pdoknlv3.WMSWFS](obj O, configMapNames types.Hash }, }, { - Name: ConfigMapVolumeName, - VolumeSource: v1.VolumeSource{ - ConfigMap: &v1.ConfigMapVolumeSource{ - LocalObjectReference: v1.LocalObjectReference{ - Name: configMapNames.ConfigMap, - }, - }, - }, + Name: ConfigMapVolumeName, + VolumeSource: newVolumeSource(configMapNames.ConfigMap), }, { - Name: ConfigMapMapfileGeneratorVolumeName, - VolumeSource: v1.VolumeSource{ - ConfigMap: &v1.ConfigMapVolumeSource{ - LocalObjectReference: v1.LocalObjectReference{Name: configMapNames.MapfileGenerator}, - }, - }, + Name: ConfigMapMapfileGeneratorVolumeName, + VolumeSource: newVolumeSource(configMapNames.MapfileGenerator), }, { - Name: ConfigMapCapabilitiesGeneratorVolumeName, - VolumeSource: v1.VolumeSource{ - ConfigMap: &v1.ConfigMapVolumeSource{ - LocalObjectReference: v1.LocalObjectReference{Name: configMapNames.CapabilitiesGenerator}, - }, - }, + Name: ConfigMapCapabilitiesGeneratorVolumeName, + VolumeSource: newVolumeSource(configMapNames.CapabilitiesGenerator), }, } if mapfile := obj.Mapfile(); mapfile != nil { volumes = append(volumes, v1.Volume{ - Name: "mapfile", - VolumeSource: v1.VolumeSource{ - ConfigMap: &v1.ConfigMapVolumeSource{ - LocalObjectReference: v1.LocalObjectReference{ - Name: mapfile.ConfigMapKeyRef.Name, - }, - }, - }, + Name: "mapfile", + VolumeSource: newVolumeSource(mapfile.ConfigMapKeyRef.Name), }) } if obj.Type() == pdoknlv3.ServiceTypeWMS { lgVolume := v1.Volume{ - Name: ConfigMapLegendGeneratorVolumeName, - VolumeSource: v1.VolumeSource{ - ConfigMap: &v1.ConfigMapVolumeSource{ - LocalObjectReference: v1.LocalObjectReference{Name: configMapNames.LegendGenerator}, - }, - }, + Name: ConfigMapLegendGeneratorVolumeName, + VolumeSource: newVolumeSource(configMapNames.LegendGenerator), } figVolume := v1.Volume{ - Name: ConfigMapFeatureinfoGeneratorVolumeName, - VolumeSource: v1.VolumeSource{ - ConfigMap: &v1.ConfigMapVolumeSource{ - LocalObjectReference: v1.LocalObjectReference{Name: configMapNames.FeatureInfoGenerator}, - }, - }, + Name: ConfigMapFeatureinfoGeneratorVolumeName, + VolumeSource: newVolumeSource(configMapNames.FeatureInfoGenerator), } volumes = append(volumes, lgVolume, figVolume) } if options := obj.Options(); options != nil { if options.PrefetchData != nil && *options.PrefetchData { + vol := newVolumeSource(configMapNames.BlobDownload) + vol.ConfigMap.DefaultMode = smoothoperatorutils.Pointer(int32(0777)) volumes = append(volumes, v1.Volume{ - Name: ConfigMapBlobDownloadVolumeName, - VolumeSource: v1.VolumeSource{ - ConfigMap: &v1.ConfigMapVolumeSource{ - LocalObjectReference: v1.LocalObjectReference{Name: configMapNames.BlobDownload}, - DefaultMode: smoothoperatorutils.Pointer(int32(0777)), - }, - }, + Name: ConfigMapBlobDownloadVolumeName, + VolumeSource: vol, }) } if obj.Type() == pdoknlv3.ServiceTypeWMS && options.UseWebserviceProxy() { volumes = append(volumes, v1.Volume{ - Name: ConfigMapOgcWebserviceProxyVolumeName, - VolumeSource: v1.VolumeSource{ - ConfigMap: &v1.ConfigMapVolumeSource{ - LocalObjectReference: v1.LocalObjectReference{Name: configMapNames.OgcWebserviceProxy}, - }, - }, + Name: ConfigMapOgcWebserviceProxyVolumeName, + VolumeSource: newVolumeSource(configMapNames.OgcWebserviceProxy), }) } } @@ -159,7 +137,8 @@ func GetVolumeMountsForDeployment[O pdoknlv3.WMSWFS](obj O, srvDir string) []v1. }, } - for name := range static_files.GetStaticFiles() { + staticFiles, _ := static_files.GetStaticFiles() + for _, name := range staticFiles { volumeMounts = append(volumeMounts, v1.VolumeMount{ Name: "mapserver", MountPath: srvDir + "/mapserver/config/" + name, @@ -186,7 +165,7 @@ func GetMapfileEnvVar[O pdoknlv3.WMSWFS](obj O) v1.EnvVar { return v1.EnvVar{ Name: "MS_MAPFILE", - Value: mapFileName, + Value: "/srv/data/config/mapfile/" + mapFileName, } } @@ -289,8 +268,7 @@ func GetProbesForDeployment[O pdoknlv3.WMSWFS](obj O) (livenessProbe *v1.Probe, func getLivenessProbe[O pdoknlv3.WMSWFS](obj O) *v1.Probe { webserviceType := strings.ToLower(string(obj.Type())) queryString := "SERVICE=" + webserviceType + "&request=GetCapabilities" - mimeType := "text/xml" - return getProbe(queryString, mimeType) + return getProbe(queryString, mimeTextXML) } func getReadinessProbeForWFS(wfs *pdoknlv3.WFS) (*v1.Probe, error) { @@ -298,8 +276,7 @@ func getReadinessProbeForWFS(wfs *pdoknlv3.WFS) (*v1.Probe, error) { return nil, errors.New("cannot get readiness probe for WFS, featuretypes could not be found") } queryString := "SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&TYPENAMES=" + wfs.Spec.Service.FeatureTypes[0].Name + "&STARTINDEX=0&COUNT=1" - mimeType := "text/xml" - return getProbe(queryString, mimeType), nil + return getProbe(queryString, mimeTextXML), nil } func getReadinessProbeForWMS(wms *pdoknlv3.WMS) (*v1.Probe, error) { @@ -330,8 +307,7 @@ func getStartupProbeForWFS(wfs *pdoknlv3.WFS) (*v1.Probe, error) { } queryString := "SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&TYPENAMES=" + strings.Join(typeNames, ",") + "&STARTINDEX=0&COUNT=1" - mimeType := "text/xml" - return getProbe(queryString, mimeType), nil + return getProbe(queryString, mimeTextXML), nil } func getStartupProbeForWMS(wms *pdoknlv3.WMS) (*v1.Probe, error) { @@ -361,6 +337,7 @@ func getProbe(queryString string, mimeType string) *v1.Probe { probeCmd, }, }}, + SuccessThreshold: 1, FailureThreshold: 3, InitialDelaySeconds: 20, PeriodSeconds: 10, diff --git a/internal/controller/shared_controller.go b/internal/controller/shared_controller.go index d986e0a..b2dd5eb 100644 --- a/internal/controller/shared_controller.go +++ b/internal/controller/shared_controller.go @@ -10,6 +10,7 @@ import ( "github.com/pdok/mapserver-operator/internal/controller/ogcwebserviceproxy" "github.com/pdok/mapserver-operator/internal/controller/types" appsv1 "k8s.io/api/apps/v1" + "k8s.io/apimachinery/pkg/api/resource" "strconv" "strings" "time" @@ -22,6 +23,7 @@ import ( "github.com/pdok/mapserver-operator/internal/controller/static_files" smoothoperatorv1 "github.com/pdok/smooth-operator/api/v1" "github.com/pdok/smooth-operator/model" + smoothoperatork8s "github.com/pdok/smooth-operator/pkg/k8s" smoothoperatorutils "github.com/pdok/smooth-operator/pkg/util" traefikdynamic "github.com/traefik/traefik/v3/pkg/config/dynamic" traefikiov1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" @@ -49,8 +51,8 @@ const ( downloadScriptName = "gpkg_download.sh" mapfileGeneratorInput = "input.json" srvDir = "/srv" - blobsConfigName = "blobs-config" - blobsSecretName = "blobs-secret" + blobsConfigPrefix = "blobs-" + blobsSecretPrefix = "blobs-" capabilitiesGeneratorInput = "input.yaml" postgisConfigName = "postgisConfig" postgisSecretName = "postgisSecret" @@ -82,6 +84,7 @@ type Images struct { CapabilitiesGeneratorImage string FeatureinfoGeneratorImage string OgcWebserviceProxyImage string + ApacheExporterImage string } func getReconcilerClient[R Reconciler](r R) client.Client { @@ -117,9 +120,9 @@ func getReconcilerImages[R Reconciler](r R) *Images { return nil } -func getSharedBareObjects(obj metav1.Object) []client.Object { +func getSharedBareObjects[O pdoknlv3.WMSWFS](obj O) []client.Object { return []client.Object{ - getBareDeployment(obj, MapserverName), + getBareDeployment(obj), getBareIngressRoute(obj), getBareHorizontalPodAutoScaler(obj), getBareConfigMapBlobDownload(obj), @@ -132,10 +135,14 @@ func getSharedBareObjects(obj metav1.Object) []client.Object { } } -func getBareDeployment(obj metav1.Object, mapserverName string) *appsv1.Deployment { +func getSuffixedName[O pdoknlv3.WMSWFS](obj O, suffix string) string { + return obj.GetName() + "-" + strings.ToLower(string(obj.Type())) + "-" + suffix +} + +func getBareDeployment[O pdoknlv3.WMSWFS](obj O) *appsv1.Deployment { return &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ - Name: obj.GetName() + "-" + mapserverName, + Name: getSuffixedName(obj, MapserverName), // name might become too long. not handling here. will just fail on apply. Namespace: obj.GetNamespace(), }, @@ -173,22 +180,40 @@ func mutateDeployment[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O, deployment *a if err != nil { return err } + for idx := range initContainers { + initContainers[idx].TerminationMessagePolicy = corev1.TerminationMessagePolicy("File") + initContainers[idx].TerminationMessagePath = "/dev/termination-log" + } containers, err := getContainersForDeployment(r, obj) if err != nil { return err } + annotations := smoothoperatorutils.CloneOrEmptyMap(deployment.Spec.Template.GetAnnotations()) + annotations["cluster-autoscaler.kubernetes.io/safe-to-evict"] = "true" + + annotations["kubectl.kubernetes.io/default-container"] = "mapserver" + annotations["match-regex.version-checker.io/mapserver"] = `^\d\.\d\.\d.*$` + annotations["prometheus.io/scrape"] = "true" + annotations["prometheus.io/port"] = "9117" + annotations["priority.version-checker.io/mapserver"] = "4" + annotations["priority.version-checker.io/ogc-webservice-proxy"] = "4" + deployment.Spec.Template = corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Annotations: map[string]string{}, + Annotations: smoothoperatorutils.CloneOrEmptyMap(deployment.Spec.Template.GetAnnotations()), Labels: labels, }, Spec: corev1.PodSpec{ + RestartPolicy: corev1.RestartPolicyAlways, TerminationGracePeriodSeconds: smoothoperatorutils.Pointer(int64(60)), InitContainers: initContainers, Volumes: mapserver.GetVolumesForDeployment(obj, configMapNames), Containers: containers, + SecurityContext: deployment.Spec.Template.Spec.SecurityContext, + SchedulerName: deployment.Spec.Template.Spec.SchedulerName, + DNSPolicy: corev1.DNSClusterFirst, }, } @@ -200,8 +225,18 @@ func mutateDeployment[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O, deployment *a } func getInitContainerForDeployment[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O) ([]corev1.Container, error) { + blobsConfig, err := smoothoperatork8s.GetConfigMap(getReconcilerClient(r), obj.GetNamespace(), blobsConfigPrefix, make(map[string]string)) + if err != nil { + return nil, err + } + + blobsSecret, err := smoothoperatork8s.GetSecret(getReconcilerClient(r), obj.GetNamespace(), blobsSecretPrefix, make(map[string]string)) + if err != nil { + return nil, err + } + images := getReconcilerImages(r) - blobDownloadInitContainer, err := blobdownload.GetBlobDownloadInitContainer(obj, images.MultitoolImage, blobsConfigName, blobsSecretName, srvDir) + blobDownloadInitContainer, err := blobdownload.GetBlobDownloadInitContainer(obj, images.MultitoolImage, blobsConfig.Name, blobsSecret.Name, srvDir) if err != nil { return nil, err } @@ -245,12 +280,41 @@ func getInitContainerForDeployment[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O) func getContainersForDeployment[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O) ([]corev1.Container, error) { images := getReconcilerImages(r) + blobsSecret, err := smoothoperatork8s.GetSecret(getReconcilerClient(r), obj.GetNamespace(), blobsSecretPrefix, make(map[string]string)) + if err != nil { + return nil, err + } + livenessProbe, readinessProbe, startupProbe, err := mapserver.GetProbesForDeployment(obj) if err != nil { return nil, err } containers := []corev1.Container{ + { + Name: "apache-exporter", + Image: images.ApacheExporterImage, + ImagePullPolicy: corev1.PullIfNotPresent, + TerminationMessagePolicy: corev1.TerminationMessageReadFile, + TerminationMessagePath: "/dev/termination-log", + Ports: []corev1.ContainerPort{ + { + ContainerPort: 9117, + Protocol: corev1.ProtocolTCP, + }, + }, + Args: []string{ + "--scrape_uri=http://localhost/server-status?auto", + }, + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceMemory: resource.MustParse("48M"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("0.02"), + }, + }, + }, { Name: MapserverName, Image: images.MapserverImage, @@ -258,17 +322,22 @@ func getContainersForDeployment[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O) ([] Ports: []corev1.ContainerPort{ { ContainerPort: 80, + Protocol: corev1.ProtocolTCP, }, }, - Env: mapserver.GetEnvVarsForDeployment(obj, blobsSecretName), - VolumeMounts: mapserver.GetVolumeMountsForDeployment(obj, srvDir), - Resources: mapserver.GetResourcesForDeployment(obj), - LivenessProbe: livenessProbe, - ReadinessProbe: readinessProbe, - StartupProbe: startupProbe, + Env: mapserver.GetEnvVarsForDeployment(obj, blobsSecret.Name), + VolumeMounts: mapserver.GetVolumeMountsForDeployment(obj, srvDir), + Resources: mapserver.GetResourcesForDeployment(obj), + TerminationMessagePolicy: corev1.TerminationMessageReadFile, + TerminationMessagePath: "/dev/termination-log", + LivenessProbe: livenessProbe, + ReadinessProbe: readinessProbe, + StartupProbe: startupProbe, Lifecycle: &corev1.Lifecycle{ PreStop: &corev1.LifecycleHandler{ - Sleep: &corev1.SleepAction{Seconds: 15}, + Exec: &corev1.ExecAction{ + Command: []string{"sleep", "15"}, + }, }, }, }, @@ -287,10 +356,10 @@ func getContainersForDeployment[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O) ([] return containers, nil } -func getBareIngressRoute(obj metav1.Object) *traefikiov1alpha1.IngressRoute { +func getBareIngressRoute[O pdoknlv3.WMSWFS](obj O) *traefikiov1alpha1.IngressRoute { return &traefikiov1alpha1.IngressRoute{ ObjectMeta: metav1.ObjectMeta{ - Name: obj.GetName() + "-" + MapserverName, + Name: getSuffixedName(obj, MapserverName), Namespace: obj.GetNamespace(), }, } @@ -452,26 +521,36 @@ func makeUptimeName[O pdoknlv3.WMSWFS](obj O) (string, error) { } func getMatchRule[O pdoknlv3.WMSWFS](obj O) string { - return "Host(`" + pdoknlv3.GetHost() + "`) && Path(`/" + pdoknlv3.GetBaseURLPath(obj) + "`)" + host := pdoknlv3.GetHost(false) + if strings.Contains(host, "localhost") { + return "Host(`localhost`) && Path(`/" + pdoknlv3.GetBaseURLPath(obj) + "`)" + } + + return "(Host(`localhost`) || Host(`" + host + "`)) && Path(`/" + pdoknlv3.GetBaseURLPath(obj) + "`)" } func getLegendMatchRule(wms *pdoknlv3.WMS) string { - return "Host(`" + pdoknlv3.GetHost() + "`) && Path(`/" + pdoknlv3.GetBaseURLPath(wms) + "/legend`)" + host := pdoknlv3.GetHost(false) + if strings.Contains(host, "localhost") { + return "Host(`localhost`) && Path(`/" + pdoknlv3.GetBaseURLPath(wms) + "/legend`)" + } + + return "(Host(`localhost`) || Host(`" + host + "`)) && Path(`/" + pdoknlv3.GetBaseURLPath(wms) + "/legend`)" } -func getBareConfigMapMapfileGenerator(obj metav1.Object) *corev1.ConfigMap { +func getBareConfigMapMapfileGenerator[O pdoknlv3.WMSWFS](obj O) *corev1.ConfigMap { return &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: obj.GetName() + "-mapfile-generator", + Name: getSuffixedName(obj, "mapfile-generator"), Namespace: obj.GetNamespace(), }, } } -func getBareConfigMapCapabilitiesGenerator(obj metav1.Object) *corev1.ConfigMap { +func getBareConfigMapCapabilitiesGenerator[O pdoknlv3.WMSWFS](obj O) *corev1.ConfigMap { return &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: obj.GetName() + "-capabilities-generator", + Name: getSuffixedName(obj, "capabilities-generator"), Namespace: obj.GetNamespace(), }, } @@ -512,11 +591,11 @@ func mutateConfigMapMapfileGenerator[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O } if len(configMap.Data) == 0 { - //mapfileGeneratorConfig, err := mapfilegenerator.GetConfig(obj, ownerInfo) - // if err != nil { - // return err - // } - mapfileGeneratorConfig := "TODO" // TODO Implement mapfilegenerator.GetConfig for WMS + mapfileGeneratorConfig, err := mapfilegenerator.GetConfig(obj, ownerInfo) + if err != nil { + return err + } + // mapfileGeneratorConfig := "TODO" // TODO Implement mapfilegenerator.GetConfig for WMS configMap.Data = map[string]string{mapfileGeneratorInput: mapfileGeneratorConfig} } configMap.Immutable = smoothoperatorutils.Pointer(true) @@ -530,10 +609,10 @@ func mutateConfigMapMapfileGenerator[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O return smoothoperatorutils.AddHashSuffix(configMap) } -func getBareHorizontalPodAutoScaler(obj metav1.Object) *autoscalingv2.HorizontalPodAutoscaler { +func getBareHorizontalPodAutoScaler[O pdoknlv3.WMSWFS](obj O) *autoscalingv2.HorizontalPodAutoscaler { return &autoscalingv2.HorizontalPodAutoscaler{ ObjectMeta: metav1.ObjectMeta{ - Name: obj.GetName() + "-" + MapserverName, + Name: getSuffixedName(obj, MapserverName), Namespace: obj.GetNamespace(), }, } @@ -542,7 +621,7 @@ func getBareHorizontalPodAutoScaler(obj metav1.Object) *autoscalingv2.Horizontal func mutateHorizontalPodAutoscaler[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O, autoscaler *autoscalingv2.HorizontalPodAutoscaler) error { autoscalerPatch := obj.HorizontalPodAutoscalerPatch() podSpecPatch := obj.PodSpecPatch() - var behaviourStabilizationWindowSeconds int32 = 0 + var behaviourStabilizationWindowSeconds int32 if obj.Type() == pdoknlv3.ServiceTypeWFS { behaviourStabilizationWindowSeconds = 300 } @@ -568,7 +647,7 @@ func mutateHorizontalPodAutoscaler[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O, } if len(metrics) == 0 { var avgU int32 = 90 - if podSpecPatch != nil && podSpecPatch.Resources.Requests.Cpu() != nil { + if podSpecPatch != nil && podSpecPatch.Resources != nil && podSpecPatch.Resources.Requests.Cpu() != nil { avgU = 80 } metrics = append(metrics, autoscalingv2.MetricSpec{ @@ -586,7 +665,7 @@ func mutateHorizontalPodAutoscaler[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O, autoscaler.Spec = autoscalingv2.HorizontalPodAutoscalerSpec{ ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{ Kind: "Deployment", - Name: obj.GetName() + "-" + MapserverName, + Name: getSuffixedName(obj, MapserverName), }, MinReplicas: &minReplicas, MaxReplicas: maxReplicas, @@ -628,10 +707,10 @@ func mutateHorizontalPodAutoscaler[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O, return ctrl.SetControllerReference(obj, autoscaler, getReconcilerScheme(r)) } -func getBareConfigMapBlobDownload(obj metav1.Object) *corev1.ConfigMap { +func getBareConfigMapBlobDownload[O pdoknlv3.WMSWFS](obj O) *corev1.ConfigMap { return &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: obj.GetName() + "-init-scripts", + Name: getSuffixedName(obj, "init-scripts"), Namespace: obj.GetNamespace(), }, } @@ -660,10 +739,10 @@ func mutateConfigMapBlobDownload[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O, co return smoothoperatorutils.AddHashSuffix(configMap) } -func getBareService(obj metav1.Object) *corev1.Service { +func getBareService[O pdoknlv3.WMSWFS](obj O) *corev1.Service { return &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ - Name: obj.GetName() + "-" + MapserverName, + Name: getSuffixedName(obj, MapserverName), Namespace: obj.GetNamespace(), }, } @@ -680,14 +759,16 @@ func mutateService[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O, service *corev1. ports := []corev1.ServicePort{ { - Name: mapserverPortName, - Port: int32(mapserverPortNr), - Protocol: corev1.ProtocolTCP, + Name: mapserverPortName, + Port: int32(mapserverPortNr), + TargetPort: intstr.FromInt32(int32(mapserverPortNr)), + Protocol: corev1.ProtocolTCP, }, { - Name: metricPortName, - Port: int32(metricPortNr), - Protocol: corev1.ProtocolTCP, + Name: metricPortName, + Port: int32(metricPortNr), + TargetPort: intstr.FromInt32(int32(metricPortNr)), + Protocol: corev1.ProtocolTCP, }, } @@ -701,8 +782,15 @@ func mutateService[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O, service *corev1. } service.Spec = corev1.ServiceSpec{ - Ports: ports, - Selector: selector, + Type: corev1.ServiceTypeClusterIP, + ClusterIP: service.Spec.ClusterIP, + ClusterIPs: service.Spec.ClusterIPs, + IPFamilyPolicy: service.Spec.IPFamilyPolicy, + IPFamilies: service.Spec.IPFamilies, + SessionAffinity: corev1.ServiceAffinityNone, + InternalTrafficPolicy: smoothoperatorutils.Pointer(corev1.ServiceInternalTrafficPolicyCluster), + Ports: ports, + Selector: selector, } if err := smoothoperatorutils.EnsureSetGVK(reconcilerClient, service, service); err != nil { return err @@ -710,10 +798,10 @@ func mutateService[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O, service *corev1. return ctrl.SetControllerReference(obj, service, getReconcilerScheme(r)) } -func getBareCorsHeadersMiddleware(obj metav1.Object) *traefikiov1alpha1.Middleware { +func getBareCorsHeadersMiddleware[O pdoknlv3.WMSWFS](obj O) *traefikiov1alpha1.Middleware { return &traefikiov1alpha1.Middleware{ ObjectMeta: metav1.ObjectMeta{ - Name: obj.GetName() + "-" + corsHeadersName, + Name: getSuffixedName(obj, corsHeadersName), // name might become too long. not handling here. will just fail on apply. Namespace: obj.GetNamespace(), UID: obj.GetUID(), @@ -748,10 +836,10 @@ func mutateCorsHeadersMiddleware[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O, mi return ctrl.SetControllerReference(obj, middleware, getReconcilerScheme(r)) } -func getBarePodDisruptionBudget(obj metav1.Object) *v1.PodDisruptionBudget { +func getBarePodDisruptionBudget[O pdoknlv3.WMSWFS](obj O) *v1.PodDisruptionBudget { return &v1.PodDisruptionBudget{ ObjectMeta: metav1.ObjectMeta{ - Name: obj.GetName() + "-" + MapserverName, + Name: getSuffixedName(obj, MapserverName), Namespace: obj.GetNamespace(), }, } @@ -779,10 +867,10 @@ func mutatePodDisruptionBudget[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O, podD return ctrl.SetControllerReference(obj, podDisruptionBudget, getReconcilerScheme(r)) } -func getBareConfigMap(obj metav1.Object) *corev1.ConfigMap { +func getBareConfigMap[O pdoknlv3.WMSWFS](obj O) *corev1.ConfigMap { return &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: obj.GetName() + "-" + MapserverName, + Name: getSuffixedName(obj, MapserverName), Namespace: obj.GetNamespace(), }, } @@ -799,7 +887,9 @@ func mutateConfigMap[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O, configMap *cor configMap.Immutable = smoothoperatorutils.Pointer(true) configMap.Data = map[string]string{} - for name, content := range static_files.GetStaticFiles() { + staticFileName, contents := static_files.GetStaticFiles() + for _, name := range staticFileName { + content := contents[name] if name == "include.conf" { content = []byte(strings.ReplaceAll(string(content), "/{{ service_path }}", mapperutils.GetPath(obj))) } @@ -1036,10 +1126,16 @@ func createOrUpdateAllForWMSWFS[R Reconciler, O pdoknlv3.WMSWFS](ctx context.Con // region Deployment { - deployment := getBareDeployment(obj, MapserverName) + deployment := getBareDeployment(obj) operationResults[smoothoperatorutils.GetObjectFullName(reconcilerClient, deployment)], err = controllerutil.CreateOrUpdate(ctx, reconcilerClient, deployment, func() error { return mutateDeployment(r, obj, deployment, hashedConfigMapNames) }) + // if operationResults[smoothoperatorutils.GetObjectFullName(reconcilerClient, deployment)] == controllerutil.OperationResultUpdated { + // deployment = getBareDeployment(obj) + // smoothoperatork8s.ShowDiff(ctx, reconcilerClient, deployment, func() error { + // return mutateDeployment(r, obj, deployment, hashedConfigMapNames) + // }) + // } if err != nil { return operationResults, fmt.Errorf("unable to create/update resource %s: %w", smoothoperatorutils.GetObjectFullName(reconcilerClient, deployment), err) } diff --git a/internal/controller/shared_controller_test.go b/internal/controller/shared_controller_test.go index 858a357..2eb3b75 100644 --- a/internal/controller/shared_controller_test.go +++ b/internal/controller/shared_controller_test.go @@ -20,11 +20,12 @@ const ( testImageName4 = "test.test/image:test4" testImageName5 = "test.test/image:test5" testImageName6 = "test.test/image:test6" + testImageName7 = "test.test/image:test7" ) func getHashedConfigMapNameFromClient[O pdoknlv3.WMSWFS](ctx context.Context, obj O, volumeName string) (string, error) { deployment := &appsv1.Deployment{} - err := k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: getBareDeployment(obj, MapserverName).GetName()}, deployment) + err := k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: getBareDeployment(obj).GetName()}, deployment) if err != nil { return "", err } diff --git a/internal/controller/static_files/reader.go b/internal/controller/static_files/reader.go index a45a63f..3180670 100644 --- a/internal/controller/static_files/reader.go +++ b/internal/controller/static_files/reader.go @@ -2,19 +2,23 @@ package static_files import ( "embed" + "sort" ) //go:embed files var embeddedFiles embed.FS -func GetStaticFiles() map[string][]byte { +func GetStaticFiles() ([]string, map[string][]byte) { + orderedNames := []string{} result := map[string][]byte{} files, _ := embeddedFiles.ReadDir("files") for _, f := range files { content, _ := embeddedFiles.ReadFile("files/" + f.Name()) result[f.Name()] = content + orderedNames = append(orderedNames, f.Name()) } + sort.Strings(orderedNames) - return result + return orderedNames, result } diff --git a/internal/controller/suite_test.go b/internal/controller/suite_test.go index fb9f596..278611f 100644 --- a/internal/controller/suite_test.go +++ b/internal/controller/suite_test.go @@ -24,6 +24,7 @@ SOFTWARE. package controller +//nolint:revive // Complains about the dot imports import ( "context" "encoding/json" @@ -32,6 +33,8 @@ import ( smoothoperator1 "github.com/pdok/smooth-operator/api/v1" traefikiov1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1" "golang.org/x/tools/go/packages" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" "os" @@ -123,6 +126,25 @@ var _ = BeforeSuite(func() { k8sClient, err = client.New(cfg, client.Options{Scheme: scheme}) Expect(err).NotTo(HaveOccurred()) Expect(k8sClient).NotTo(BeNil()) + + // Deploy blob configmap + secret + blobConfig := &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: blobsConfigPrefix + "testtest", + Namespace: metav1.NamespaceDefault, + }, + } + err = k8sClient.Create(ctx, blobConfig) + Expect(err).NotTo(HaveOccurred()) + + blobSecret := v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: blobsSecretPrefix + "testtest", + Namespace: metav1.NamespaceDefault, + }, + } + err = k8sClient.Create(ctx, &blobSecret) + Expect(err).NotTo(HaveOccurred()) }) var _ = AfterSuite(func() { diff --git a/internal/controller/test_manifests/v3_wfs.yaml b/internal/controller/test_manifests/v3_wfs.yaml index e78b988..4d508b5 100644 --- a/internal/controller/test_manifests/v3_wfs.yaml +++ b/internal/controller/test_manifests/v3_wfs.yaml @@ -38,7 +38,7 @@ spec: prefetchData: false includeIngress: false service: - prefix: "" + prefix: "test" url: https://service.pdok.nl/eigenaar/dataset/wfs/1.0.0 inspire: serviceMetadataUrl: diff --git a/internal/controller/wfs_controller.go b/internal/controller/wfs_controller.go index 01d5787..147458b 100644 --- a/internal/controller/wfs_controller.go +++ b/internal/controller/wfs_controller.go @@ -50,6 +50,7 @@ type WFSReconciler struct { // +kubebuilder:rbac:groups=pdok.nl,resources=ownerinfo/status,verbs=get // +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;delete // +kubebuilder:rbac:groups=core,resources=configmaps;services,verbs=watch;create;get;update;list;delete +// +kubebuilder:rbac:groups=core,resources=secrets,verbs=watch;list;get // +kubebuilder:rbac:groups=autoscaling,resources=horizontalpodautoscalers,verbs=watch;create;get;update;list;delete // +kubebuilder:rbac:groups=traefik.io,resources=ingressroutes;middlewares,verbs=get;list;watch;create;update;delete // +kubebuilder:rbac:groups=policy,resources=poddisruptionbudgets,verbs=create;update;delete;list;watch @@ -84,7 +85,7 @@ func (r *WFSReconciler) Reconcile(ctx context.Context, req ctrl.Request) (result // Fetch the OwnerInfo instance ownerInfo := &smoothoperatorv1.OwnerInfo{} objectKey := client.ObjectKey{ - Namespace: "default", // wfs.Namespace, + Namespace: wfs.Namespace, Name: wfs.Spec.Service.OwnerInfoRef, } if err := r.Client.Get(ctx, objectKey, ownerInfo); err != nil { diff --git a/internal/controller/wfs_controller_test.go b/internal/controller/wfs_controller_test.go index a685029..ac55661 100644 --- a/internal/controller/wfs_controller_test.go +++ b/internal/controller/wfs_controller_test.go @@ -24,6 +24,7 @@ SOFTWARE. package controller +//nolint:revive // Complains about the dot imports import ( "context" _ "embed" @@ -177,7 +178,7 @@ var _ = Describe("WFS Controller", func() { reconcileWFS(controllerReconciler, wfs, typeNamespacedNameWfs) By("Getting the original Deployment") - deployment := getBareDeployment(wfs, MapserverName) + deployment := getBareDeployment(wfs) Eventually(func() bool { err := k8sClient.Get(ctx, client.ObjectKeyFromObject(deployment), deployment) return Expect(err).NotTo(HaveOccurred()) @@ -215,13 +216,13 @@ var _ = Describe("WFS Controller", func() { By("Reconciling the WFS and checking the deployment") reconcileWFS(controllerReconciler, wfs, typeNamespacedNameWfs) - deployment := getBareDeployment(wfs, MapserverName) + deployment := getBareDeployment(wfs) Eventually(func() bool { err := k8sClient.Get(ctx, client.ObjectKeyFromObject(deployment), deployment) return Expect(err).NotTo(HaveOccurred()) }, "10s", "1s").Should(BeTrue()) - Expect(deployment.GetName()).Should(Equal(wfs.GetName() + "-mapserver")) + Expect(deployment.GetName()).Should(Equal(wfs.GetName() + "-wfs-mapserver")) Expect(deployment.GetNamespace()).Should(Equal(namespace)) Expect(deployment.Spec.Template.Spec.TerminationGracePeriodSeconds).Should(Equal(smoothoperatorutils.Pointer(int64(60)))) @@ -234,7 +235,7 @@ var _ = Describe("WFS Controller", func() { /** Container tests */ - container := deployment.Spec.Template.Spec.Containers[0] + container := deployment.Spec.Template.Spec.Containers[1] Expect(container.Name).Should(Equal("mapserver")) Expect(container.Ports[0].ContainerPort).Should(Equal(int32(80))) Expect(container.Image).Should(Equal(reconcilerImages.MapserverImage)) @@ -279,11 +280,11 @@ var _ = Describe("WFS Controller", func() { volumeMounts := []v1.VolumeMount{ {Name: "base", MountPath: "/srv/data"}, {Name: "data", MountPath: "/var/www"}, - {Name: mapserver.ConfigMapBlobDownloadVolumeName, MountPath: "/src/scripts", ReadOnly: true}, + {Name: mapserver.ConfigMapBlobDownloadVolumeName, MountPath: "/srv/scripts", ReadOnly: true}, } envFrom := []v1.EnvFromSource{ - utils.NewEnvFromSource(utils.EnvFromSourceTypeConfigMap, "blobs-config"), - utils.NewEnvFromSource(utils.EnvFromSourceTypeSecret, "blobs-secret"), + utils.NewEnvFromSource(utils.EnvFromSourceTypeConfigMap, "blobs-testtest"), + utils.NewEnvFromSource(utils.EnvFromSourceTypeSecret, "blobs-testtest"), } Expect(blobDownloadContainer.VolumeMounts).Should(Equal(volumeMounts)) Expect(blobDownloadContainer.EnvFrom).Should(Equal(envFrom)) @@ -374,7 +375,7 @@ var _ = Describe("WFS Controller", func() { }, "10s", "1s").Should(BeTrue()) // Make sure the name is hashed - Expect(configMap.GetName()).To(HavePrefix(wfs.GetName() + "-mapserver-")) + Expect(configMap.GetName()).To(HavePrefix(wfs.GetName() + "-wfs-mapserver")) Expect(configMap.GetNamespace()).To(Equal(namespace)) Expect(configMap.Immutable).To(Equal(smoothoperatorutils.Pointer(true))) @@ -411,7 +412,7 @@ var _ = Describe("WFS Controller", func() { return Expect(err).NotTo(HaveOccurred()) }, "10s", "1s").Should(BeTrue()) - Expect(configMap.GetName()).To(HavePrefix(wfs.GetName() + "-mapfile-generator-")) + Expect(configMap.GetName()).To(HavePrefix(wfs.GetName() + "-wfs-mapfile-generator-")) Expect(configMap.GetNamespace()).To(Equal(namespace)) Expect(configMap.Immutable).To(Equal(smoothoperatorutils.Pointer(true))) checkWFSLabels(configMap.GetLabels()) @@ -436,7 +437,7 @@ var _ = Describe("WFS Controller", func() { return Expect(err).NotTo(HaveOccurred()) }, "10s", "1s").Should(BeTrue()) - Expect(configMap.GetName()).To(HavePrefix(wfs.GetName() + "-init-scripts-")) + Expect(configMap.GetName()).To(HavePrefix(wfs.GetName() + "-wfs-init-scripts-")) Expect(configMap.GetNamespace()).To(Equal(namespace)) Expect(configMap.Immutable).To(Equal(smoothoperatorutils.Pointer(true))) checkWFSLabels(configMap.GetLabels()) @@ -461,7 +462,7 @@ var _ = Describe("WFS Controller", func() { return Expect(err).NotTo(HaveOccurred()) }, "10s", "1s").Should(BeTrue()) - Expect(configMap.GetName()).To(HavePrefix(wfs.GetName() + "-capabilities-generator-")) + Expect(configMap.GetName()).To(HavePrefix(wfs.GetName() + "-wfs-capabilities-generator-")) Expect(configMap.GetNamespace()).To(Equal(namespace)) Expect(configMap.Immutable).To(Equal(smoothoperatorutils.Pointer(true))) checkWFSLabels(configMap.GetLabels()) @@ -484,7 +485,7 @@ var _ = Describe("WFS Controller", func() { return Expect(err).NotTo(HaveOccurred()) }, "10s", "1s").Should(BeTrue()) - Expect(middlewareCorsHeaders.Name).Should(Equal(wfs.GetName() + "-mapserver-headers")) + Expect(middlewareCorsHeaders.Name).Should(Equal(wfs.GetName() + "-wfs-mapserver-headers")) Expect(middlewareCorsHeaders.Namespace).Should(Equal("default")) checkWFSLabels(middlewareCorsHeaders.GetLabels()) // Expect(middlewareCorsHeaders.Spec.Headers.FrameDeny).Should(Equal(true)) @@ -510,7 +511,7 @@ var _ = Describe("WFS Controller", func() { */ checkWFSLabels(podDisruptionBudget.GetLabels(), podDisruptionBudget.Spec.Selector.MatchLabels) - Expect(podDisruptionBudget.GetName()).To(Equal(wfs.GetName() + "-mapserver")) + Expect(podDisruptionBudget.GetName()).To(Equal(wfs.GetName() + "-wfs-mapserver")) Expect(podDisruptionBudget.Spec.MaxUnavailable.IntValue()).Should(Equal(1)) }) @@ -526,10 +527,10 @@ var _ = Describe("WFS Controller", func() { return Expect(err).NotTo(HaveOccurred()) }, "10s", "1s").Should(BeTrue()) - Expect(autoscaler.GetName()).To(Equal(wfs.GetName() + "-mapserver")) + Expect(autoscaler.GetName()).To(Equal(wfs.GetName() + "-wfs-mapserver")) Expect(autoscaler.Spec.ScaleTargetRef).To(Equal(v2.CrossVersionObjectReference{ Kind: "Deployment", - Name: wfs.GetName() + "-mapserver", + Name: wfs.GetName() + "-wfs-mapserver", })) /** @@ -595,7 +596,7 @@ var _ = Describe("WFS Controller", func() { return Expect(err).NotTo(HaveOccurred()) }, "10s", "1s").Should(BeTrue()) - Expect(service.GetName()).To(Equal(wfs.GetName() + "-mapserver")) + Expect(service.GetName()).To(Equal(wfs.GetName() + "-wfs-mapserver")) Expect(service.Spec.Ports).To(Equal([]v1.ServicePort{ { Name: "mapserver", @@ -638,17 +639,17 @@ var _ = Describe("WFS Controller", func() { "uptime.pdok.nl/url": "https://service.pdok.nl/eigenaar/dataset/wfs/1.0.0", })) - Expect(ingressRoute.GetName()).To(Equal(wfs.GetName() + "-mapserver")) + Expect(ingressRoute.GetName()).To(Equal(wfs.GetName() + "-wfs-mapserver")) Expect(len(ingressRoute.Spec.Routes)).To(Equal(1)) Expect(ingressRoute.Spec.Routes[0]).To(Equal(traefikiov1alpha1.Route{ Kind: "Rule", Match: "Host(`localhost`) && Path(`/eigenaar/dataset/wfs/1.0.0`)", - Middlewares: []traefikiov1alpha1.MiddlewareRef{{Name: wfs.GetName() + "-mapserver-headers", Namespace: "default"}}, + Middlewares: []traefikiov1alpha1.MiddlewareRef{{Name: wfs.GetName() + "-wfs-mapserver-headers", Namespace: "default"}}, Services: []traefikiov1alpha1.Service{{ LoadBalancerSpec: traefikiov1alpha1.LoadBalancerSpec{ Kind: "Service", Port: intstr.FromInt32(80), - Name: wfs.GetName() + "-mapserver", + Name: wfs.GetName() + "-wfs-mapserver", }, }}, })) @@ -711,6 +712,7 @@ func getWFSReconciler() *WFSReconciler { MapfileGeneratorImage: testImageName2, MapserverImage: testImageName3, CapabilitiesGeneratorImage: testImageName4, + ApacheExporterImage: testImageName5, }, } } diff --git a/internal/controller/wms_controller.go b/internal/controller/wms_controller.go index e042a51..c2e1013 100644 --- a/internal/controller/wms_controller.go +++ b/internal/controller/wms_controller.go @@ -61,7 +61,12 @@ type WMSReconciler struct { // +kubebuilder:rbac:groups=pdok.nl,resources=ownerinfo/status,verbs= // +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;delete // +kubebuilder:rbac:groups=core,resources=configmaps;services,verbs=watch;create;get;update;list;delete +// +kubebuilder:rbac:groups=core,resources=secrets,verbs=watch;list;get // +kubebuilder:rbac:groups=traefik.io,resources=ingressroutes;middlewares,verbs=get;list;watch;create;update;delete +// +kubebuilder:rbac:groups=autoscaling,resources=horizontalpodautoscalers,verbs=watch;create;get;update;list;delete +// +kubebuilder:rbac:groups=policy,resources=poddisruptionbudgets,verbs=create;update;delete;list;watch +// +kubebuilder:rbac:groups=policy,resources=poddisruptionbudgets/status,verbs=get;update +// +kubebuilder:rbac:groups=policy,resources=poddisruptionbudgets/finalizers,verbs=update // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. diff --git a/internal/controller/wms_controller_test.go b/internal/controller/wms_controller_test.go index f7cddaa..7a2a6ed 100644 --- a/internal/controller/wms_controller_test.go +++ b/internal/controller/wms_controller_test.go @@ -24,6 +24,7 @@ SOFTWARE. package controller +//nolint:revive // Complains about the dot imports import ( "context" _ "embed" @@ -174,7 +175,7 @@ var _ = Describe("WMS Controller", func() { reconcileWMS(controllerReconciler, wms, typeNamespacedNameWms) By("Getting the original Deployment") - deployment := getBareDeployment(wms, MapserverName) + deployment := getBareDeployment(wms) Eventually(func() bool { err := k8sClient.Get(ctx, client.ObjectKeyFromObject(deployment), deployment) return Expect(err).NotTo(HaveOccurred()) @@ -211,13 +212,13 @@ var _ = Describe("WMS Controller", func() { By("Reconciling the WMS and checking the deployment") reconcileWMS(controllerReconciler, wms, typeNamespacedNameWms) - deployment := getBareDeployment(wms, MapserverName) + deployment := getBareDeployment(wms) Eventually(func() bool { err := k8sClient.Get(ctx, client.ObjectKeyFromObject(deployment), deployment) return Expect(err).NotTo(HaveOccurred()) }, "10s", "1s").Should(BeTrue()) - Expect(deployment.GetName()).Should(Equal(wms.GetName() + "-mapserver")) + Expect(deployment.GetName()).Should(Equal(wms.GetName() + "-wms-mapserver")) Expect(deployment.GetNamespace()).Should(Equal(namespace)) Expect(deployment.Spec.Template.Spec.TerminationGracePeriodSeconds).Should(Equal(smoothoperatorutils.Pointer(int64(60)))) @@ -230,7 +231,7 @@ var _ = Describe("WMS Controller", func() { /** Container tests */ - container := deployment.Spec.Template.Spec.Containers[0] + container := deployment.Spec.Template.Spec.Containers[1] Expect(container.Name).Should(Equal("mapserver")) Expect(container.Ports[0].ContainerPort).Should(Equal(int32(80))) Expect(container.Image).Should(Equal(reconcilerImages.MapserverImage)) @@ -275,11 +276,11 @@ var _ = Describe("WMS Controller", func() { volumeMounts := []v1.VolumeMount{ {Name: "base", MountPath: "/srv/data"}, {Name: "data", MountPath: "/var/www"}, - {Name: mapserver.ConfigMapBlobDownloadVolumeName, MountPath: "/src/scripts", ReadOnly: true}, + {Name: mapserver.ConfigMapBlobDownloadVolumeName, MountPath: "/srv/scripts", ReadOnly: true}, } envFrom := []v1.EnvFromSource{ - utils.NewEnvFromSource(utils.EnvFromSourceTypeConfigMap, "blobs-config"), - utils.NewEnvFromSource(utils.EnvFromSourceTypeSecret, "blobs-secret"), + utils.NewEnvFromSource(utils.EnvFromSourceTypeConfigMap, "blobs-testtest"), + utils.NewEnvFromSource(utils.EnvFromSourceTypeSecret, "blobs-testtest"), } Expect(blobDownloadContainer.VolumeMounts).Should(Equal(volumeMounts)) Expect(blobDownloadContainer.EnvFrom).Should(Equal(envFrom)) @@ -373,7 +374,7 @@ var _ = Describe("WMS Controller", func() { }, "10s", "1s").Should(BeTrue()) // Make sure the name is hashed - Expect(configMap.GetName()).To(HavePrefix(wms.GetName() + "-mapserver-")) + Expect(configMap.GetName()).To(HavePrefix(wms.GetName() + "-wms-mapserver-")) Expect(configMap.GetNamespace()).To(Equal(namespace)) Expect(configMap.Immutable).To(Equal(smoothoperatorutils.Pointer(true))) @@ -410,7 +411,7 @@ var _ = Describe("WMS Controller", func() { return Expect(err).NotTo(HaveOccurred()) }, "10s", "1s").Should(BeTrue()) - Expect(configMap.GetName()).To(HavePrefix(wms.GetName() + "-mapfile-generator-")) + Expect(configMap.GetName()).To(HavePrefix(wms.GetName() + "-wms-mapfile-generator-")) Expect(configMap.GetNamespace()).To(Equal(namespace)) Expect(configMap.Immutable).To(Equal(smoothoperatorutils.Pointer(true))) checkWMSLabels(configMap.GetLabels()) @@ -435,7 +436,7 @@ var _ = Describe("WMS Controller", func() { return Expect(err).NotTo(HaveOccurred()) }, "10s", "1s").Should(BeTrue()) - Expect(configMap.GetName()).To(HavePrefix(wms.GetName() + "-init-scripts-")) + Expect(configMap.GetName()).To(HavePrefix(wms.GetName() + "-wms-init-scripts-")) Expect(configMap.GetNamespace()).To(Equal(namespace)) Expect(configMap.Immutable).To(Equal(smoothoperatorutils.Pointer(true))) checkWMSLabels(configMap.GetLabels()) @@ -460,7 +461,7 @@ var _ = Describe("WMS Controller", func() { return Expect(err).NotTo(HaveOccurred()) }, "10s", "1s").Should(BeTrue()) - Expect(configMap.GetName()).To(HavePrefix(wms.GetName() + "-capabilities-generator-")) + Expect(configMap.GetName()).To(HavePrefix(wms.GetName() + "-wms-capabilities-generator-")) Expect(configMap.GetNamespace()).To(Equal(namespace)) Expect(configMap.Immutable).To(Equal(smoothoperatorutils.Pointer(true))) checkWMSLabels(configMap.GetLabels()) @@ -549,7 +550,7 @@ var _ = Describe("WMS Controller", func() { return Expect(err).NotTo(HaveOccurred()) }, "10s", "1s").Should(BeTrue()) - Expect(middlewareCorsHeaders.Name).Should(Equal(wms.GetName() + "-mapserver-headers")) + Expect(middlewareCorsHeaders.Name).Should(Equal(wms.GetName() + "-wms-mapserver-headers")) Expect(middlewareCorsHeaders.Namespace).Should(Equal("default")) checkWMSLabels(middlewareCorsHeaders.GetLabels()) // Expect(middlewareCorsHeaders.Spec.Headers.FrameDeny).Should(Equal(true)) @@ -575,7 +576,7 @@ var _ = Describe("WMS Controller", func() { */ checkWMSLabels(podDisruptionBudget.GetLabels(), podDisruptionBudget.Spec.Selector.MatchLabels) - Expect(podDisruptionBudget.GetName()).To(Equal(wms.GetName() + "-mapserver")) + Expect(podDisruptionBudget.GetName()).To(Equal(wms.GetName() + "-wms-mapserver")) Expect(podDisruptionBudget.Spec.MaxUnavailable.IntValue()).Should(Equal(1)) }) @@ -591,10 +592,10 @@ var _ = Describe("WMS Controller", func() { return Expect(err).NotTo(HaveOccurred()) }, "10s", "1s").Should(BeTrue()) - Expect(autoscaler.GetName()).To(Equal(wms.GetName() + "-mapserver")) + Expect(autoscaler.GetName()).To(Equal(wms.GetName() + "-wms-mapserver")) Expect(autoscaler.Spec.ScaleTargetRef).To(Equal(v2.CrossVersionObjectReference{ Kind: "Deployment", - Name: wms.GetName() + "-mapserver", + Name: wms.GetName() + "-wms-mapserver", })) /** @@ -660,7 +661,7 @@ var _ = Describe("WMS Controller", func() { return Expect(err).NotTo(HaveOccurred()) }, "10s", "1s").Should(BeTrue()) - Expect(service.GetName()).To(Equal(wms.GetName() + "-mapserver")) + Expect(service.GetName()).To(Equal(wms.GetName() + "-wms-mapserver")) Expect(service.Spec.Ports).To(Equal([]v1.ServicePort{ { Name: "mapserver", @@ -709,29 +710,29 @@ var _ = Describe("WMS Controller", func() { "uptime.pdok.nl/url": "https://service.pdok.nl/owner/dataset/wms/1.0.0", })) - Expect(ingressRoute.GetName()).To(Equal(wms.GetName() + "-mapserver")) + Expect(ingressRoute.GetName()).To(Equal(wms.GetName() + "-wms-mapserver")) Expect(len(ingressRoute.Spec.Routes)).To(Equal(2)) Expect(ingressRoute.Spec.Routes[0]).To(Equal(traefikiov1alpha1.Route{ Kind: "Rule", Match: "Host(`localhost`) && Path(`/owner/dataset/wms/1.0.0/legend`)", - Middlewares: []traefikiov1alpha1.MiddlewareRef{{Name: wms.GetName() + "-mapserver-headers", Namespace: "default"}}, + Middlewares: []traefikiov1alpha1.MiddlewareRef{{Name: wms.GetName() + "-wms-mapserver-headers", Namespace: "default"}}, Services: []traefikiov1alpha1.Service{{ LoadBalancerSpec: traefikiov1alpha1.LoadBalancerSpec{ Kind: "Service", Port: intstr.FromInt32(80), - Name: wms.GetName() + "-mapserver", + Name: wms.GetName() + "-wms-mapserver", }, }}, })) Expect(ingressRoute.Spec.Routes[1]).To(Equal(traefikiov1alpha1.Route{ Kind: "Rule", Match: "Host(`localhost`) && Path(`/owner/dataset/wms/1.0.0`)", - Middlewares: []traefikiov1alpha1.MiddlewareRef{{Name: wms.GetName() + "-mapserver-headers", Namespace: "default"}}, + Middlewares: []traefikiov1alpha1.MiddlewareRef{{Name: wms.GetName() + "-wms-mapserver-headers", Namespace: "default"}}, Services: []traefikiov1alpha1.Service{{ LoadBalancerSpec: traefikiov1alpha1.LoadBalancerSpec{ Kind: "Service", Port: intstr.FromInt32(9111), - Name: wms.GetName() + "-mapserver", + Name: wms.GetName() + "-wms-mapserver", }, }}, })) @@ -796,6 +797,7 @@ func getWMSReconciler() *WMSReconciler { CapabilitiesGeneratorImage: testImageName4, FeatureinfoGeneratorImage: testImageName5, OgcWebserviceProxyImage: testImageName6, + ApacheExporterImage: testImageName7, }, } } diff --git a/internal/webhook/v3/webhook_suite_test.go b/internal/webhook/v3/webhook_suite_test.go index 6923ef4..dc4f16f 100644 --- a/internal/webhook/v3/webhook_suite_test.go +++ b/internal/webhook/v3/webhook_suite_test.go @@ -24,6 +24,7 @@ SOFTWARE. package v3 +//nolint:revive // Complains about the dot imports import ( "context" "crypto/tls" @@ -90,8 +91,11 @@ var _ = BeforeSuite(func() { By("bootstrapping test environment") testEnv = &envtest.Environment{ - Scheme: scheme, - CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "config", "crd", "bases")}, + Scheme: scheme, + CRDDirectoryPaths: []string{ + filepath.Join("..", "..", "config", "crd", "bases", "pdok.nl_wfs.yaml"), + filepath.Join("..", "..", "config", "crd", "bases", "pdok.nl_wms.yaml"), + }, ErrorIfCRDPathMissing: false, CRDInstallOptions: envtest.CRDInstallOptions{ Scheme: scheme, @@ -110,8 +114,7 @@ var _ = BeforeSuite(func() { // cfg is defined in this file globally. cfg, err = testEnv.Start() - // TODO enabling next line causes the tests to fail, find out why - // Expect(err).NotTo(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(cfg).NotTo(BeNil()) k8sClient, err = client.New(cfg, client.Options{Scheme: scheme}) diff --git a/internal/webhook/v3/wfs_webhook.go b/internal/webhook/v3/wfs_webhook.go index 98a2ee3..ddb6067 100644 --- a/internal/webhook/v3/wfs_webhook.go +++ b/internal/webhook/v3/wfs_webhook.go @@ -64,7 +64,7 @@ type WFSCustomValidator struct { var _ webhook.CustomValidator = &WFSCustomValidator{} // ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type WFS. -func (v *WFSCustomValidator) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) { +func (v *WFSCustomValidator) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) { wfs, ok := obj.(*pdoknlv3.WFS) if !ok { return nil, fmt.Errorf("expected a WFS object but got %T", obj) @@ -75,7 +75,7 @@ func (v *WFSCustomValidator) ValidateCreate(ctx context.Context, obj runtime.Obj } // ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type WFS. -func (v *WFSCustomValidator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { +func (v *WFSCustomValidator) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { wfs, ok := newObj.(*pdoknlv3.WFS) if !ok { return nil, fmt.Errorf("expected a WFS object for the newObj but got %T", newObj) @@ -90,7 +90,7 @@ func (v *WFSCustomValidator) ValidateUpdate(ctx context.Context, oldObj, newObj } // ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type WFS. -func (v *WFSCustomValidator) ValidateDelete(ctx context.Context, obj runtime.Object) (admission.Warnings, error) { +func (v *WFSCustomValidator) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) { wfs, ok := obj.(*pdoknlv3.WFS) if !ok { return nil, fmt.Errorf("expected a WFS object but got %T", obj) diff --git a/internal/webhook/v3/wfs_webhook_test.go b/internal/webhook/v3/wfs_webhook_test.go index c1dd5ae..f029520 100644 --- a/internal/webhook/v3/wfs_webhook_test.go +++ b/internal/webhook/v3/wfs_webhook_test.go @@ -24,6 +24,7 @@ SOFTWARE. package v3 +//nolint:revive // Complains about the dot imports import ( "context" . "github.com/onsi/ginkgo/v2" @@ -67,7 +68,7 @@ var _ = Describe("WFS Webhook", func() { }) It("Warns if the name contains WFS", func() { - obj.Name = obj.Name + "-wfs" + obj.Name += "-wfs" warnings, err := validator.ValidateCreate(ctx, obj) Expect(err).To(BeNil()) Expect(len(warnings)).To(BeNumerically(">", 0)) diff --git a/internal/webhook/v3/wms_webhook.go b/internal/webhook/v3/wms_webhook.go index 832efce..e1e8dc3 100644 --- a/internal/webhook/v3/wms_webhook.go +++ b/internal/webhook/v3/wms_webhook.go @@ -63,7 +63,7 @@ type WMSCustomValidator struct { var _ webhook.CustomValidator = &WMSCustomValidator{} // ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type WMS. -func (v *WMSCustomValidator) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) { +func (v *WMSCustomValidator) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) { wms, ok := obj.(*pdoknlv3.WMS) if !ok { return nil, fmt.Errorf("expected a WMS object but got %T", obj) @@ -74,7 +74,7 @@ func (v *WMSCustomValidator) ValidateCreate(ctx context.Context, obj runtime.Obj } // ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type WMS. -func (v *WMSCustomValidator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { +func (v *WMSCustomValidator) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { wms, ok := newObj.(*pdoknlv3.WMS) if !ok { return nil, fmt.Errorf("expected a WMS object for the newObj but got %T", newObj) @@ -89,7 +89,7 @@ func (v *WMSCustomValidator) ValidateUpdate(ctx context.Context, oldObj, newObj } // ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type WMS. -func (v *WMSCustomValidator) ValidateDelete(ctx context.Context, obj runtime.Object) (admission.Warnings, error) { +func (v *WMSCustomValidator) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) { wms, ok := obj.(*pdoknlv3.WMS) if !ok { return nil, fmt.Errorf("expected a WMS object but got %T", obj) diff --git a/internal/webhook/v3/wms_webhook_test.go b/internal/webhook/v3/wms_webhook_test.go index 17fbebf..7c40e7a 100644 --- a/internal/webhook/v3/wms_webhook_test.go +++ b/internal/webhook/v3/wms_webhook_test.go @@ -24,6 +24,7 @@ SOFTWARE. package v3 +//nolint:revive // Complains about the dot imports import ( "context" . "github.com/onsi/ginkgo/v2" diff --git a/test/e2e/e2e_suite_test.go b/test/e2e/e2e_suite_test.go index a3245e0..ed2d505 100644 --- a/test/e2e/e2e_suite_test.go +++ b/test/e2e/e2e_suite_test.go @@ -16,6 +16,7 @@ limitations under the License. package e2e +//nolint:revive // Complains about the dot imports import ( "fmt" "os" diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index 31fd8a8..89a995b 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -16,6 +16,7 @@ limitations under the License. package e2e +//nolint:revive // Complains about the dot imports import ( "encoding/json" "fmt" diff --git a/test/utils/utils.go b/test/utils/utils.go index a934556..fef95da 100644 --- a/test/utils/utils.go +++ b/test/utils/utils.go @@ -197,7 +197,7 @@ func GetProjectDir() (string, error) { if err != nil { return wd, err } - wd = strings.Replace(wd, "/test/e2e", "", -1) + wd = strings.ReplaceAll(wd, "/test/e2e", "") return wd, nil }