Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 111 additions & 19 deletions api/v3/shared_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const (
ServiceTypeWFS ServiceType = "WFS"
)

// WMSWFS is the common interface used for both WMS and WFS resources.
// +kubebuilder:object:generate=false
type WMSWFS interface {
*WFS | *WMS
Expand All @@ -35,86 +36,177 @@ type WMSWFS interface {
HasPostgisData() bool
// Sha1 hash of the objects name
ID() string
// URLPath returns the configured service URL
URLPath() string

GeoPackages() []*Gpkg
}

// Mapfile references a ConfigMap key where an external mapfile is stored.
// +kubebuilder:validation:Type=object
type Mapfile struct {
// +kubebuilder:validation:Type=object
ConfigMapKeyRef corev1.ConfigMapKeySelector `json:"configMapKeyRef"`
}

// Options configures optional behaviors of the operator, like ingress, casing, and data prefetching.
// +kubebuilder:validation:Type=object
type Options struct {
// IncludeIngress dictates whether to deploy an Ingress or ensure none exists.
// +kubebuilder:default:=true
IncludeIngress bool `json:"includeIngress"`

// AutomaticCasing enables automatic conversion from snake_case to camelCase.
// +kubebuilder:default:=true
AutomaticCasing bool `json:"automaticCasing"`

// ValidateRequests enables request validation against the service schema.
// +kubebuilder:default:=true
ValidateRequests *bool `json:"validateRequests,omitempty"`

// RewriteGroupToDataLayers merges group layers into individual data layers.
// +kubebuilder:default:=false
RewriteGroupToDataLayers *bool `json:"rewriteGroupToDataLayers,omitempty"`

// DisableWebserviceProxy disables the built-in proxy for external web services.
// +kubebuilder:default:=false
DisableWebserviceProxy *bool `json:"disableWebserviceProxy,omitempty"`

// Whether to prefetch data from blob storage, and store it on the local filesystem.
// If `false`, the data will be served directly out of blob storage
// +kubebuilder:default:=true
PrefetchData *bool `json:"prefetchData,omitempty"`

// ValidateChildStyleNameEqual ensures child style names match the parent style.
// +kubebuilder:default=false
ValidateChildStyleNameEqual *bool `json:"validateChildStyleNameEqual,omitempty"`
}

// Inspire holds INSPIRE-specific metadata for the service.
// +kubebuilder:validation:Type=object
type Inspire struct {
ServiceMetadataURL MetadataURL `json:"serviceMetadataUrl"`
SpatialDatasetIdentifier string `json:"spatialDatasetIdentifier"`
Language string `json:"language"`
// ServiceMetadataURL references the CSW or custom metadata record.
// +kubebuilder:validation:Type=object
ServiceMetadataURL MetadataURL `json:"serviceMetadataUrl"`

// SpatialDatasetIdentifier is the ID uniquely identifying the dataset.
// +kubebuilder:validation:MinLength:=1
SpatialDatasetIdentifier string `json:"spatialDatasetIdentifier"`

// Language of the INSPIRE metadata record
// +kubebuilder:validation:MinLength:=1
Language string `json:"language"`
}

type MetadataURL struct {
CSW *Metadata `json:"csw"`
Custom *Custom `json:"custom,omitempty"`
// CSW describes a metadata record via a metadataIdentifier (UUID).
CSW *Metadata `json:"csw"`

// Custom allows arbitrary href
Custom *Custom `json:"custom,omitempty"`
}

// Metadata holds the UUID of a CSW metadata record
type Metadata struct {
// MetadataIdentifier is the record's UUID
// +kubebuilder:validation:Format:=uuid
// +kubebuilder:validation:MinLength:=1
MetadataIdentifier string `json:"metadataIdentifier"`
}

// Custom represents a non-CSW metadata link with a href and MIME type.
// +kubebuilder:validation:Type=object
type Custom struct {
// +kubebuilder:validation:Pattern=`^https?://.*$`
// +kubebuilder:validation:MinLength=1
Href string `json:"href"`

// MIME type of the custom link
// +kubebuilder:validation:MinLength=1
Type string `json:"type"`
}

// Data holds the data source configuration
// +kubebuilder:validation:XValidation:rule="has(self.gpkg) || has(self.tif) || has(self.postgis)", message="Atleast one of the datasource should be provided (postgis, gpkg, tif)"
type Data struct {
Gpkg *Gpkg `json:"gpkg,omitempty"`
// Gpkg configures a GeoPackage file source
Gpkg *Gpkg `json:"gpkg,omitempty"`

// Postgis configures a Postgis table source
Postgis *Postgis `json:"postgis,omitempty"`
TIF *TIF `json:"tif,omitempty"`

// TIF configures a GeoTIF raster source
TIF *TIF `json:"tif,omitempty"`
}

// Gpkg configures a Geopackage data source
// +kubebuilder:validation:Type=object
type Gpkg struct {
BlobKey string `json:"blobKey"`
TableName string `json:"tableName"`
GeometryType string `json:"geometryType"`
Columns []Column `json:"columns"`
// Blobkey identifies the location/bucket of the .gpkg file
// +kubebuilder:validation:Pattern=`\.gpkg$`
// +kubebuilder:validation:MinLength:=1
BlobKey string `json:"blobKey"`

// TableName is the table within the geopackage
// +kubebuilder:validation:MinLength:=1
TableName string `json:"tableName"`

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

// Columns to visualize for this table
// +kubebuilder:validation:MinItems:=1
Columns []Column `json:"columns"`
}

// Postgis - reference to table in a Postgres database
// +kubebuilder:validation:Type=object
type Postgis struct {
TableName string `json:"tableName"`
GeometryType string `json:"geometryType"`
Columns []Column `json:"columns"`
// TableName in postGIS
// +kubebuilder:validation:MinLength=1
TableName string `json:"tableName"`

// GeometryType of the table
// +kubebuilder:validation:Pattern=`^(Multi)?(Point|LineString|Polygon)$`
// +kubebuilder:validation:MinLength:=1
GeometryType string `json:"geometryType"`

// Columns to expose from table
// +kubebuilder:validation:MinItems=1
Columns []Column `json:"columns"`
}

// TIF configures a GeoTIFF raster data source
// +kubebuilder:validation:Type=object
type TIF struct {
BlobKey string `json:"blobKey"`
Resample *string `json:"resample,omitempty"`
Offsite *string `json:"offsite,omitempty"`
GetFeatureInfoIncludesClass *bool `json:"getFeatureInfoIncludesClass,omitempty"`
// BlobKey to the TIFF file
// +kubebuilder:validation:Pattern=`\.(tif|tiff)$`
// +kubebuilder:validation:MinLength:=1
BlobKey string `json:"blobKey"`

// Resample method
// +kubebuilder:validation:MinLength:=1
Resample *string `json:"resample,omitempty"`

// Offsite color for nodata removal
// +kubebuilder:validation:MinLength:=1
Offsite *string `json:"offsite,omitempty"`

// Include class names in GetFeatureInfo responses
GetFeatureInfoIncludesClass *bool `json:"getFeatureInfoIncludesClass,omitempty"`
}

// Column maps a source column name to an optional alias for output.
// +kubebuilder:validation:Type=object
type Column struct {
Name string `json:"name"`
// Name of the column in the data source.
// +kubebuilder:validation:MinLength=1
Name string `json:"name"`

// Alias for the column in the service output.
// +kubebuilder:validation:MinLength=1
Alias *string `json:"alias,omitempty"`
}

Expand Down
123 changes: 99 additions & 24 deletions api/v3/wfs_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,59 +66,134 @@ func init() {

// WFSSpec vertegenwoordigt de hoofdstruct voor de YAML-configuratie
type WFSSpec struct {
// Optional lifecycle settings
Lifecycle *shared_model.Lifecycle `json:"lifecycle,omitempty"`

// +kubebuilder:validation:Type=object
// +kubebuilder:validation:Schemaless
// +kubebuilder:pruning:PreserveUnknownFields
// Optional strategic merge patch for the pod in the deployment. E.g. to patch the resources or add extra env vars.
PodSpecPatch *corev1.PodSpec `json:"podSpecPatch,omitempty"`
HorizontalPodAutoscalerPatch *autoscalingv2.HorizontalPodAutoscalerSpec `json:"horizontalPodAutoscalerPatch,omitempty"`
Options Options `json:"options,omitempty"`
Service WFSService `json:"service"`

// service configuration
Service WFSService `json:"service"`
}

type WFSService struct {
// Geonovum subdomein
// +kubebuilder:validation:MinLength:=1
Prefix string `json:"prefix"`
URL string `json:"url"`
Inspire *Inspire `json:"inspire,omitempty"`
Mapfile *Mapfile `json:"mapfile,omitempty"`
OwnerInfoRef string `json:"ownerInfoRef"`
Title string `json:"title"`
Abstract string `json:"abstract"`
Keywords []string `json:"keywords"`
Fees *string `json:"fees,omitempty"`
Prefix string `json:"prefix"`

// URL of the service
// +kubebuilder:validation:Pattern:=`^https?://.*$`
// +kubebuilder:validation:MinLength:=1
URL string `json:"url"`

// Config for Inspire services
Inspire *Inspire `json:"inspire,omitempty"`

// External Mapfile reference
Mapfile *Mapfile `json:"mapfile,omitempty"`

// Reference to OwnerInfo CR
// +kubebuilder:validation:MinLength:=1
OwnerInfoRef string `json:"ownerInfoRef"`

// Service title
// +kubebuilder:validation:MinLength:=1
Title string `json:"title"`

// Service abstract
// +kubebuilder:validation:MinLength:=1
Abstract string `json:"abstract"`

// Keywords for capabilities
// +kubebuilder:validation:MinItems:=1
Keywords []string `json:"keywords"`

// Optional Fees
// +kubebuilder:validation:MinLength:=1
Fees *string `json:"fees,omitempty"`

// AccessConstraints URL
// +kubebuilder:validation:Pattern:="https?://"
// +kubebuilder:default="https://creativecommons.org/publicdomain/zero/1.0/deed.nl"
AccessConstraints string `json:"accessConstraints"`
DefaultCrs string `json:"defaultCrs"`
OtherCrs []string `json:"otherCrs,omitempty"`
Bbox *Bbox `json:"bbox,omitempty"`
// +kubebuilder:validation:MinLength:=1
AccessConstraints string `json:"accessConstraints"`

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

// Other supported CRS
// +kubebuilder:validation:MinItems:=1
OtherCrs []string `json:"otherCrs,omitempty"`

// Service bounding box
Bbox *Bbox `json:"bbox,omitempty"`

// CountDefault -> wfs_maxfeatures in mapfile
CountDefault *string `json:"countDefault,omitempty"`
// +kubebuilder:validation:MinLength:=1
CountDefault *string `json:"countDefault,omitempty"`

// FeatureTypes configurations
// +kubebuilder:validation:MinItems:=1
// +kubebuilder:validation:Type=array
FeatureTypes []FeatureType `json:"featureTypes"`
}

type Bbox struct {
// EXTENT/wfs_extent in mapfile
//nolint:tagliatelle
// +kubebuilder:validation:Type=object
DefaultCRS shared_model.BBox `json:"defaultCRS"`
}

// FeatureType defines a WFS feature
type FeatureType struct {
Name string `json:"name"`
Title string `json:"title"`
Abstract string `json:"abstract"`
Keywords []string `json:"keywords"`
DatasetMetadataURL MetadataURL `json:"datasetMetadataUrl"`
Bbox *FeatureBbox `json:"bbox,omitempty"`
Data Data `json:"data"`
// Name of the feature
// +kubebuilder:validation:MinLength:=1
Name string `json:"name"`

// Title of the feature
// +kubebuilder:validation:MinLength:=1
Title string `json:"title"`

// Abstract of the feature
// +kubebuilder:validation:MinLength:=1
Abstract string `json:"abstract"`

// Keywords of the feature
// +kubebuilder:validation:MinItems:=1
Keywords []string `json:"keywords"`

// Metadata URL
// +kubebuilder:validation:Type=object
DatasetMetadataURL MetadataURL `json:"datasetMetadataUrl"`

// Optional feature bbox
// +kubebuilder:validation:Optional
// +kubebuilder:validation:Type:=object
Bbox *FeatureBbox `json:"bbox,omitempty"`

// FeatureType data connection
// +kubebuilder:validation:Type=object
Data Data `json:"data"`
}

// FeatureType bounding box, if provided it overrides the default extent
type FeatureBbox struct {
// DefaultCRS defines the feature’s bounding box in the service’s own CRS
//nolint:tagliatelle
DefaultCRS shared_model.BBox `json:"defaultCRS"`
WGS84 *shared_model.BBox `json:"wgs84,omitempty"`
// +kubebuilder:validation:Type=object
DefaultCRS shared_model.BBox `json:"defaultCRS"`

// WGS84, if provided, gives the same bounding box reprojected into EPSG:4326.
// +kubebuilder:validation:Type=object
WGS84 *shared_model.BBox `json:"wgs84,omitempty"`
}

func (wfs *WFS) HasPostgisData() bool {
Expand Down
Loading
Loading