Skip to content

Commit

Permalink
refactor(config): Re-order some funcs + add readme
Browse files Browse the repository at this point in the history
  • Loading branch information
rkettelerij committed Sep 13, 2024
1 parent ecbadf6 commit 72c34ec
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 63 deletions.
6 changes: 6 additions & 0 deletions config/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Config

This config package is used to validate and unmarshall a GoKoala YAML config file to structs.

In addition, this package is imported as a _library_ in the PDOK [OGCAPI operator](https://github.com/PDOK/ogcapi-operator)
to validate the `OGCAPI` Custom Resource (CR) in order to orchestrate GoKoala in Kubernetes.
17 changes: 17 additions & 0 deletions config/collections.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,23 @@ type GeoSpatialCollectionMetadata struct {
StorageCrs *string `yaml:"storageCrs,omitempty" json:"storageCrs,omitempty" default:"http://www.opengis.net/def/crs/OGC/1.3/CRS84" validate:"startswith=http://www.opengis.net/def/crs"`
}

// +kubebuilder:object:generate=true
type Extent struct {
// Projection (SRS/CRS) to be used. When none is provided WGS84 (http://www.opengis.net/def/crs/OGC/1.3/CRS84) is used.
// +optional
// +kubebuilder:validation:Pattern=`^EPSG:\d+$`
Srs string `yaml:"srs,omitempty" json:"srs,omitempty" validate:"omitempty,startswith=EPSG:"`

// Geospatial extent
Bbox []string `yaml:"bbox" json:"bbox"`

// Temporal extent
// +optional
// +kubebuilder:validation:MinItems=2
// +kubebuilder:validation:MaxItems=2
Interval []string `yaml:"interval,omitempty" json:"interval,omitempty" validate:"omitempty,len=2"`
}

// +kubebuilder:object:generate=true
type CollectionLinks struct {
// Links to downloads of entire collection. These will be rendered as rel=enclosure links
Expand Down
86 changes: 23 additions & 63 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,29 @@ func (c *Config) AllCollections() GeoSpatialCollections {
return result
}

// +kubebuilder:object:generate=true
type OgcAPI struct {
// Enable when this API should offer OGC API 3D GeoVolumes. This includes OGC 3D Tiles.
// +optional
GeoVolumes *OgcAPI3dGeoVolumes `yaml:"3dgeovolumes,omitempty" json:"3dgeovolumes,omitempty"`

// Enable when this API should offer OGC API Tiles. This also requires OGC API Styles.
// +optional
Tiles *OgcAPITiles `yaml:"tiles,omitempty" json:"tiles,omitempty" validate:"required_with=Styles"`

// Enable when this API should offer OGC API Styles.
// +optional
Styles *OgcAPIStyles `yaml:"styles,omitempty" json:"styles,omitempty"`

// Enable when this API should offer OGC API Features.
// +optional
Features *OgcAPIFeatures `yaml:"features,omitempty" json:"features,omitempty"`

// Enable when this API should offer OGC API Processes.
// +optional
Processes *OgcAPIProcesses `yaml:"processes,omitempty" json:"processes,omitempty"`
}

// +kubebuilder:object:generate=true
type Support struct {
// Name of the support organization
Expand Down Expand Up @@ -178,46 +201,6 @@ type Resources struct {
Directory *string `yaml:"directory,omitempty" json:"directory,omitempty" validate:"required_without=URL,omitempty,dirpath|filepath"`
}

// +kubebuilder:object:generate=true
type OgcAPI struct {
// Enable when this API should offer OGC API 3D GeoVolumes. This includes OGC 3D Tiles.
// +optional
GeoVolumes *OgcAPI3dGeoVolumes `yaml:"3dgeovolumes,omitempty" json:"3dgeovolumes,omitempty"`

// Enable when this API should offer OGC API Tiles. This also requires OGC API Styles.
// +optional
Tiles *OgcAPITiles `yaml:"tiles,omitempty" json:"tiles,omitempty" validate:"required_with=Styles"`

// Enable when this API should offer OGC API Styles.
// +optional
Styles *OgcAPIStyles `yaml:"styles,omitempty" json:"styles,omitempty"`

// Enable when this API should offer OGC API Features.
// +optional
Features *OgcAPIFeatures `yaml:"features,omitempty" json:"features,omitempty"`

// Enable when this API should offer OGC API Processes.
// +optional
Processes *OgcAPIProcesses `yaml:"processes,omitempty" json:"processes,omitempty"`
}

// +kubebuilder:object:generate=true
type Extent struct {
// Projection (SRS/CRS) to be used. When none is provided WGS84 (http://www.opengis.net/def/crs/OGC/1.3/CRS84) is used.
// +optional
// +kubebuilder:validation:Pattern=`^EPSG:\d+$`
Srs string `yaml:"srs,omitempty" json:"srs,omitempty" validate:"omitempty,startswith=EPSG:"`

// Geospatial extent
Bbox []string `yaml:"bbox" json:"bbox"`

// Temporal extent
// +optional
// +kubebuilder:validation:MinItems=2
// +kubebuilder:validation:MaxItems=2
Interval []string `yaml:"interval,omitempty" json:"interval,omitempty" validate:"omitempty,len=2"`
}

// +kubebuilder:object:generate=true
type License struct {
// Name of the license, e.g. MIT, CC0, etc
Expand Down Expand Up @@ -266,29 +249,6 @@ func validate(config *Config) error {
return nil
}

func validateFeatureCollections(collections GeoSpatialCollections) error {
var errMessages []string
for _, collection := range collections {
if collection.Metadata != nil && collection.Metadata.TemporalProperties != nil &&
(collection.Metadata.Extent == nil || collection.Metadata.Extent.Interval == nil) {
errMessages = append(errMessages, fmt.Sprintf("validation failed for collection '%s'; "+
"field 'Extent.Interval' is required with field 'TemporalProperties'\n", collection.ID))
}
if collection.Features != nil && collection.Features.Filters.Properties != nil {
for _, pf := range collection.Features.Filters.Properties {
if pf.AllowedValues != nil && *pf.DeriveAllowedValuesFromDatasource {
errMessages = append(errMessages, fmt.Sprintf("validation failed for property filter '%s'; "+
"field 'AllowedValues' and field 'DeriveAllowedValuesFromDatasource' are mutually exclusive\n", pf.Name))
}
}
}
}
if len(errMessages) > 0 {
return fmt.Errorf("invalid config provided:\n%v", errMessages)
}
return nil
}

// validateLocalPaths validates the existence of local paths.
// Not suitable for general validation while unmarshalling.
// Because that could happen on another machine.
Expand Down
23 changes: 23 additions & 0 deletions config/ogcapi_features.go
Original file line number Diff line number Diff line change
Expand Up @@ -406,3 +406,26 @@ type TemporalProperties struct {
// Name of field in datasource to be used in temporal queries as the end date
EndDate string `yaml:"endDate" json:"endDate" validate:"required"`
}

func validateFeatureCollections(collections GeoSpatialCollections) error {
var errMessages []string
for _, collection := range collections {
if collection.Metadata != nil && collection.Metadata.TemporalProperties != nil &&
(collection.Metadata.Extent == nil || collection.Metadata.Extent.Interval == nil) {
errMessages = append(errMessages, fmt.Sprintf("validation failed for collection '%s'; "+
"field 'Extent.Interval' is required with field 'TemporalProperties'\n", collection.ID))
}
if collection.Features != nil && collection.Features.Filters.Properties != nil {
for _, pf := range collection.Features.Filters.Properties {
if pf.AllowedValues != nil && *pf.DeriveAllowedValuesFromDatasource {
errMessages = append(errMessages, fmt.Sprintf("validation failed for property filter '%s'; "+
"field 'AllowedValues' and field 'DeriveAllowedValuesFromDatasource' are mutually exclusive\n", pf.Name))
}
}
}
}
if len(errMessages) > 0 {
return fmt.Errorf("invalid config provided:\n%v", errMessages)
}
return nil
}

0 comments on commit 72c34ec

Please sign in to comment.