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
8 changes: 5 additions & 3 deletions api/v2beta1/shared_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func ConvertAutoscaling(src Autoscaling) *pdoknlv3.HorizontalPodAutoscalerPatch

return &pdoknlv3.HorizontalPodAutoscalerPatch{
MinReplicas: minReplicas,
MaxReplicas: maxReplicas,
MaxReplicas: &maxReplicas,
Metrics: metrics,
}
}
Expand Down Expand Up @@ -221,8 +221,10 @@ func NewV2KubernetesObject(lifecycle *smoothoperatormodel.Lifecycle, podSpecPatc
kub.Resources = &podSpecPatch.Containers[0].Resources

if scalingSpec != nil {
kub.Autoscaling = &Autoscaling{
MaxReplicas: smoothoperatorutils.Pointer(int(scalingSpec.MaxReplicas)),
kub.Autoscaling = &Autoscaling{}

if scalingSpec.MaxReplicas != nil {
kub.Autoscaling.MaxReplicas = smoothoperatorutils.Pointer(int(*scalingSpec.MaxReplicas))
}

if scalingSpec.MinReplicas != nil {
Expand Down
39 changes: 33 additions & 6 deletions api/v2beta1/wfs_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ package v2beta1

import (
"log"
"strconv"

pdoknlv3 "github.com/pdok/mapserver-operator/api/v3"
smoothoperatormodel "github.com/pdok/smooth-operator/model"
Expand All @@ -43,7 +44,7 @@ func (src *WFS) ConvertTo(dstRaw conversion.Hub) error {
return src.ToV3(dst)
}

//nolint:gosec
//nolint:gosec,funlen,cyclop
func (src *WFS) ToV3(dst *pdoknlv3.WFS) error {
dst.ObjectMeta = src.ObjectMeta

Expand Down Expand Up @@ -76,6 +77,20 @@ func (src *WFS) ToV3(dst *pdoknlv3.WFS) error {
return err
}

accessConstraints, err := url.Parse("https://creativecommons.org/publicdomain/zero/1.0/deed.nl")
if err != nil {
return err
}
if src.Spec.Service.AccessConstraints != nil {
accessConstraints, err = url.Parse(*src.Spec.Service.AccessConstraints)
if err != nil {
return err
}
}

if err != nil {
return err
}
service := pdoknlv3.WFSService{
Prefix: src.Spec.General.Dataset,
URL: *url,
Expand All @@ -84,7 +99,7 @@ func (src *WFS) ToV3(dst *pdoknlv3.WFS) error {
Abstract: src.Spec.Service.Abstract,
Keywords: src.Spec.Service.Keywords,
Fees: nil,
AccessConstraints: src.Spec.Service.AccessConstraints,
AccessConstraints: smoothoperatormodel.URL{URL: accessConstraints},
DefaultCrs: src.Spec.Service.DataEPSG,
OtherCrs: []string{
"EPSG::25831",
Expand All @@ -95,10 +110,17 @@ func (src *WFS) ToV3(dst *pdoknlv3.WFS) error {
"EPSG::4258",
"EPSG::4326",
},
CountDefault: src.Spec.Service.Maxfeatures,
FeatureTypes: make([]pdoknlv3.FeatureType, 0),
}

if src.Spec.Service.Maxfeatures != nil {
maxFeatures, err := strconv.Atoi(*src.Spec.Service.Maxfeatures)
if err != nil {
return err
}
service.CountDefault = &maxFeatures
}

if src.Spec.Service.Mapfile != nil {
service.Mapfile = &pdoknlv3.Mapfile{
ConfigMapKeyRef: src.Spec.Service.Mapfile.ConfigMapKeyRef,
Expand Down Expand Up @@ -148,7 +170,7 @@ func convertV2FeatureTypeToV3(src FeatureType) pdoknlv3.FeatureType {
Title: src.Title,
Abstract: src.Abstract,
Keywords: src.Keywords,
DatasetMetadataURL: pdoknlv3.MetadataURL{
DatasetMetadataURL: &pdoknlv3.MetadataURL{
CSW: &pdoknlv3.Metadata{
MetadataIdentifier: src.DatasetMetadataIdentifier,
},
Expand Down Expand Up @@ -190,19 +212,24 @@ func (dst *WFS) ConvertFrom(srcRaw conversion.Hub) error {
}
}

accessConstraints := src.Spec.Service.AccessConstraints.String()

service := WFSService{
Title: src.Spec.Service.Title,
Abstract: src.Spec.Service.Abstract,
Keywords: src.Spec.Service.Keywords,
AccessConstraints: src.Spec.Service.AccessConstraints,
AccessConstraints: &accessConstraints,
DataEPSG: src.Spec.Service.DefaultCrs,
Maxfeatures: src.Spec.Service.CountDefault,
Authority: Authority{
Name: "",
URL: "",
},
}

if src.Spec.Service.CountDefault != nil {
service.Maxfeatures = smoothoperatorutils.Pointer(strconv.Itoa(*src.Spec.Service.CountDefault))
}

if src.Spec.Service.Bbox != nil {
service.Extent = smoothoperatorutils.Pointer(src.Spec.Service.Bbox.DefaultCRS.ToExtent())
} else {
Expand Down
4 changes: 2 additions & 2 deletions api/v3/shared_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const (
// This way we don't have to specify the scaleTargetRef field in the CRD.
type HorizontalPodAutoscalerPatch struct {
MinReplicas *int32 `json:"minReplicas,omitempty"`
MaxReplicas int32 `json:"maxReplicas"`
MaxReplicas *int32 `json:"maxReplicas,omitempty"`
Metrics []autoscalingv2.MetricSpec `json:"metrics,omitempty"`
Behavior *autoscalingv2.HorizontalPodAutoscalerBehavior `json:"behavior,omitempty"`
}
Expand Down Expand Up @@ -167,7 +167,7 @@ type Data struct {
// +kubebuilder:validation:Type=object
type Gpkg struct {
// Blobkey identifies the location/bucket of the .gpkg file
// +kubebuilder:validation:Pattern=`\.gpkg$`
// +kubebuilder:validation:Pattern:=^.+\/.+\/.+\.gpkg$
// +kubebuilder:validation:MinLength:=1
BlobKey string `json:"blobKey"`

Expand Down
41 changes: 41 additions & 0 deletions api/v3/shared_validation.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package v3

import (
"fmt"

sharedValidation "github.com/pdok/smooth-operator/pkg/validation"
v1 "k8s.io/api/core/v1"

apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/util/validation/field"
Expand Down Expand Up @@ -34,3 +37,41 @@ func ValidateUpdate[W WMSWFS](newW, oldW W, validate func(W, *[]string, *field.E
newW.GroupKind(),
newW.GetName(), allErrs)
}

func ValidateHorizontalPodAutoscalerPatch(patch HorizontalPodAutoscalerPatch, allErrs *field.ErrorList) {
path := field.NewPath("spec").Child("horizontalPodAutoscaler")
// TODO: replace hardcoded defaults with dynamic defaults from cli options or ownerInfo
var minReplicas, maxReplicas int32 = 2, 32
if patch.MinReplicas != nil {
minReplicas = *patch.MinReplicas
}
if patch.MaxReplicas != nil {
maxReplicas = *patch.MaxReplicas
}

if maxReplicas < minReplicas {
replicas := fmt.Sprintf("minReplicas: %d, maxReplicas: %d", minReplicas, maxReplicas)

*allErrs = append(*allErrs, field.Invalid(path, replicas, "maxReplicas cannot be less than minReplicas"))
}

}

func ValidateEphemeralStorage(podSpecPatch v1.PodSpec, allErrs *field.ErrorList) {
path := field.NewPath("spec").
Child("podSpecPatch").
Child("containers").
Key("mapserver").
Child("resources").
Child("limits").
Child(v1.ResourceEphemeralStorage.String())
storageSet := false
for _, container := range podSpecPatch.Containers {
if container.Name == "mapserver" {
_, storageSet = container.Resources.Limits[v1.ResourceEphemeralStorage]
}
}
if !storageSet {
*allErrs = append(*allErrs, field.Required(path, ""))
}
}
14 changes: 8 additions & 6 deletions api/v3/wfs_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,17 +118,16 @@ type WFSService struct {

// Keywords for capabilities
// +kubebuilder:validation:MinItems:=1
// +kubebuilder:validation:items:MinLength:=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"
// +kubebuilder:validation:MinLength:=1
AccessConstraints *string `json:"accessConstraints,omitempty"`
AccessConstraints smoothoperatormodel.URL `json:"accessConstraints,omitempty"`

// Default CRS (DataEPSG)
// +kubebuilder:validation:Pattern:="^EPSG:(28992|25831|25832|3034|3035|3857|4258|4326)$"
Expand All @@ -143,8 +142,8 @@ type WFSService struct {
Bbox *Bbox `json:"bbox,omitempty"`

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

// FeatureTypes configurations
// +kubebuilder:validation:MinItems:=1
Expand All @@ -164,6 +163,8 @@ func (s WFSService) KeywordsIncludingInspireKeyword() []string {
// HealthCheck is the struct with all fields to configure custom healthchecks
type HealthCheckWFS struct {
// +kubebuilder:validation:MinLength:=1
// +kubebuilder:validation:XValidation:rule="self.contains('Service=WFS')",message="a valid healthcheck contains 'Service=WFS'"
// +kubebuilder:validation:XValidation:rule="self.contains('Request=')",message="a valid healthcheck contains 'Request='"
Querystring string `json:"querystring"`
// +kubebuilder:validation:Pattern=(image/png|text/xml|text/html)
Mimetype string `json:"mimetype"`
Expand Down Expand Up @@ -192,11 +193,12 @@ type FeatureType struct {

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

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

// Optional feature bbox
// +kubebuilder:validation:Optional
Expand Down
25 changes: 4 additions & 21 deletions api/v3/wfs_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package v3
import (
"strings"

corev1 "k8s.io/api/core/v1"

sharedValidation "github.com/pdok/smooth-operator/pkg/validation"

apierrors "k8s.io/apimachinery/pkg/api/errors"
Expand Down Expand Up @@ -58,25 +56,10 @@ func ValidateWFS(wfs *WFS, warnings *[]string, allErrs *field.ErrorList) {
sharedValidation.AddWarning(warnings, *path.Child("bbox"), "is not used when service.mapfile is configured", wfs.GroupVersionKind(), wfs.GetName())
}

if wfs.Spec.HorizontalPodAutoscalerPatch != nil {
ValidateHorizontalPodAutoscalerPatch(*wfs.Spec.HorizontalPodAutoscalerPatch, allErrs)
}

podSpecPatch := wfs.Spec.PodSpecPatch
ValidateEphemeralStorage(podSpecPatch, allErrs)
}

func ValidateEphemeralStorage(podSpecPatch corev1.PodSpec, allErrs *field.ErrorList) {
path := field.NewPath("spec").
Child("podSpecPatch").
Child("containers").
Key("mapserver").
Child("resources").
Child("limits").
Child(corev1.ResourceEphemeralStorage.String())
storageSet := false
for _, container := range podSpecPatch.Containers {
if container.Name == "mapserver" {
_, storageSet = container.Resources.Limits[corev1.ResourceEphemeralStorage]
}
}
if !storageSet {
*allErrs = append(*allErrs, field.Required(path, ""))
}
}
1 change: 1 addition & 0 deletions api/v3/wms_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ type WMSService struct {

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

// Reference to a CR of Kind OwnerInfo
Expand Down
4 changes: 4 additions & 0 deletions api/v3/wms_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,10 @@ func ValidateWMS(wms *WMS, warnings *[]string, allErrs *field.ErrorList) {
))
}

if wms.Spec.HorizontalPodAutoscalerPatch != nil {
ValidateHorizontalPodAutoscalerPatch(*wms.Spec.HorizontalPodAutoscalerPatch, allErrs)
}

podSpecPatch := wms.Spec.PodSpecPatch
ValidateEphemeralStorage(podSpecPatch, allErrs)
}
Expand Down
19 changes: 12 additions & 7 deletions api/v3/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading