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
1 change: 0 additions & 1 deletion api/v2beta1/shared_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,6 @@ func NewV2KubernetesObject(lifecycle *shared_model.Lifecycle, podSpecPatch *core
}
}

// TODO - healthcheck
if podSpecPatch != nil {
kub.Resources = &podSpecPatch.Containers[0].Resources
}
Expand Down
15 changes: 14 additions & 1 deletion api/v2beta1/wfs_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,19 @@ func (src *WFS) ToV3(dst *pdoknlv3.WFS) error {
dst.Spec.HorizontalPodAutoscalerPatch = ConvertAutoscaling(*src.Spec.Kubernetes.Autoscaling)
}

// TODO converse src.Spec.Kubernetes.HealthCheck when we know what the implementation in v3 will be
if src.Spec.Kubernetes.Resources != nil {
dst.Spec.PodSpecPatch = ConvertResources(*src.Spec.Kubernetes.Resources)
}

dst.Spec.Options = ConvertOptionsV2ToV3(src.Spec.Options)

if src.Spec.Kubernetes.HealthCheck != nil {
dst.Spec.HealthCheck = &pdoknlv3.HealthCheckWFS{
Querystring: *src.Spec.Kubernetes.HealthCheck.Querystring,
Mimetype: *src.Spec.Kubernetes.HealthCheck.Mimetype,
}
}

service := pdoknlv3.WFSService{
Prefix: src.Spec.General.Dataset,
URL: CreateBaseURL("https://service.pdok.nl", "wfs", src.Spec.General),
Expand Down Expand Up @@ -174,6 +180,13 @@ func (dst *WFS) ConvertFrom(srcRaw conversion.Hub) error {

dst.Spec.Options = ConvertOptionsV3ToV2(src.Spec.Options)

if src.Spec.HealthCheck != nil {
dst.Spec.Kubernetes.HealthCheck = &HealthCheck{
Querystring: &src.Spec.HealthCheck.Querystring,
Mimetype: &src.Spec.HealthCheck.Mimetype,
}
}

service := WFSService{
Title: src.Spec.Service.Title,
Abstract: src.Spec.Service.Abstract,
Expand Down
39 changes: 38 additions & 1 deletion api/v2beta1/wms_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@ func (src *WMS) ToV3(target *pdoknlv3.WMS) {
dst.Spec.HorizontalPodAutoscalerPatch = ConvertAutoscaling(*src.Spec.Kubernetes.Autoscaling)
}

// TODO converse src.Spec.Kubernetes.HealthCheck when we know what the implementation in v3 will be
if src.Spec.Kubernetes.Resources != nil {
dst.Spec.PodSpecPatch = ConvertResources(*src.Spec.Kubernetes.Resources)
}

dst.Spec.Options = ConvertOptionsV2ToV3(src.Spec.Options)
dst.Spec.HealthCheck = convertHealthCheckToV3(src.Spec.Kubernetes.HealthCheck)

service := pdoknlv3.WMSService{
URL: CreateBaseURL("https://service.pdok.nl", "wms", src.Spec.General),
Expand Down Expand Up @@ -141,6 +141,24 @@ func (src *WMS) ToV3(target *pdoknlv3.WMS) {
dst.Spec.Service = service
}

func convertHealthCheckToV3(v2 *HealthCheck) *pdoknlv3.HealthCheckWMS {
if v2 != nil {
switch {
case v2.Querystring != nil:
return &pdoknlv3.HealthCheckWMS{
Querystring: v2.Querystring,
Mimetype: v2.Mimetype,
}
case v2.Boundingbox != nil:
return &pdoknlv3.HealthCheckWMS{
Boundingbox: smoothoperatorutils.Pointer(sharedModel.ExtentToBBox(strings.ReplaceAll(*v2.Boundingbox, ",", " "))),
}
}
}

return nil
}

// ConvertFrom converts the Hub version (v3) to this WMS (v2beta1).
//
//nolint:revive
Expand All @@ -154,6 +172,7 @@ func (dst *WMS) ConvertFrom(srcRaw conversion.Hub) error {
dst.Spec.General = LabelsToV2General(src.ObjectMeta.Labels)

dst.Spec.Kubernetes = NewV2KubernetesObject(src.Spec.Lifecycle, src.Spec.PodSpecPatch, src.Spec.HorizontalPodAutoscalerPatch)
dst.Spec.Kubernetes.HealthCheck = convertHealthCheckToV2(src.Spec.HealthCheck)

dst.Spec.Options = ConvertOptionsV3ToV2(src.Spec.Options)

Expand Down Expand Up @@ -240,6 +259,24 @@ func (dst *WMS) ConvertFrom(srcRaw conversion.Hub) error {
return nil
}

func convertHealthCheckToV2(v3 *pdoknlv3.HealthCheckWMS) *HealthCheck {
if v3 != nil {
switch {
case v3.Querystring != nil:
return &HealthCheck{
Querystring: v3.Querystring,
Mimetype: v3.Mimetype,
}
case v3.Boundingbox != nil:
return &HealthCheck{
Boundingbox: smoothoperatorutils.Pointer(strings.ReplaceAll(v3.Boundingbox.ToExtent(), " ", ",")),
}
}
}

return nil
}

func (v2Service WMSService) GetTopLayer() (*WMSLayer, error) {
// Only one layer defined that has data
if len(v2Service.Layers) == 1 && v2Service.Layers[0].Data != nil {
Expand Down
6 changes: 1 addition & 5 deletions api/v3/shared_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,7 @@ type WMSWFS interface {

GeoPackages() []*Gpkg

ReadinessQueryString() (string, error)

// TODO implement healthcheck in CR
// StartUpQueryString() string
// LivenessQueryString() string
ReadinessQueryString() (string, string, error)
}

// Mapfile references a ConfigMap key where an external mapfile is stored.
Expand Down
22 changes: 19 additions & 3 deletions api/v3/wfs_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ type WFSSpec struct {
// TODO omitting the options field or setting an empty value results in incorrect defaulting of the options
Options *Options `json:"options,omitempty"`

// Custom healthcheck options
HealthCheck *HealthCheckWFS `json:"healthCheck,omitempty"`

// service configuration
Service WFSService `json:"service"`
}
Expand Down Expand Up @@ -159,6 +162,14 @@ func (s WFSService) KeywordsIncludingInspireKeyword() []string {
return keywords
}

// HealthCheck is the struct with all fields to configure custom healthchecks
type HealthCheckWFS struct {
// +kubebuilder:validation:MinLength:=1
Querystring string `json:"querystring"`
// +kubebuilder:validation:Pattern=(image/png|text/xml|text/html)
Mimetype string `json:"mimetype"`
}

type Bbox struct {
// EXTENT/wfs_extent in mapfile
//nolint:tagliatelle
Expand Down Expand Up @@ -278,9 +289,14 @@ func (wfs *WFS) GeoPackages() []*Gpkg {
return gpkgs
}

func (wfs *WFS) ReadinessQueryString() (string, error) {
func (wfs *WFS) ReadinessQueryString() (string, string, error) {
if hc := wfs.Spec.HealthCheck; hc != nil {
return hc.Querystring, hc.Mimetype, nil
}

if len(wfs.Spec.Service.FeatureTypes) == 0 {
return "nil", errors.New("cannot get readiness probe for WFS, featuretypes could not be found")
return "", "", errors.New("cannot get readiness probe for WFS, featuretypes could not be found")
}
return "SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&TYPENAMES=" + wfs.Spec.Service.FeatureTypes[0].Name + "&STARTINDEX=0&COUNT=1", nil

return "SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&TYPENAMES=" + wfs.Spec.Service.FeatureTypes[0].Name + "&STARTINDEX=0&COUNT=1", "text/xml", nil
}
31 changes: 26 additions & 5 deletions api/v3/wms_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ type WMSSpec struct {
// TODO omitting the options field or setting an empty value results in incorrect defaulting of the options
Options *Options `json:"options,omitempty"`

// Custom healthcheck options
HealthCheck *HealthCheckWMS `json:"healthCheck,omitempty"`

// Service specification
Service WMSService `json:"service"`
}
Expand Down Expand Up @@ -132,6 +135,18 @@ func (wmsService WMSService) KeywordsIncludingInspireKeyword() []string {
return keywords
}

// HealthCheck is the struct with all fields to configure custom healthchecks
// +kubebuilder:validation:XValidation:rule="!has(self.querystring) || has(self.mimetype)",message="mimetype is required when a querystring is used"
// +kubebuilder:validation:XValidation:rule="(has(self.boundingbox) || has(self.querystring)) && !(has(self.querystring) && has(self.boundingbox))", message="healthcheck should have querystring + mimetype or boundingbox, not both"
type HealthCheckWMS struct {
// +kubebuilder:validation:MinLength:=1
Querystring *string `json:"querystring,omitempty"`
// +kubebuilder:validation:Pattern=(image/png|text/xml|text/html)
Mimetype *string `json:"mimetype,omitempty"`

Boundingbox *shared_model.BBox `json:"boundingbox,omitempty"`
}

// +kubebuilder:validation:XValidation:message="Either blobKeys or configMapRefs is required",rule="has(self.blobKeys) || has(self.configMapRefs)"
type StylingAssets struct {
// +kubebuilder:validations:MinItems:=1
Expand Down Expand Up @@ -627,12 +642,18 @@ func (wms *WMS) GeoPackages() []*Gpkg {
}

func (wms *WMS) HealthCheckBBox() string {
// TODO make dynamic
if hc := wms.Spec.HealthCheck; hc != nil && hc.Boundingbox != nil {
return strings.ReplaceAll(hc.Boundingbox.ToExtent(), " ", ",")
}

return "190061.4619730016857,462435.5987861062749,202917.7508707302331,473761.6884966178914"
}

func (wms *WMS) ReadinessQueryString() (string, error) {
// TODO implement healthcheck from CR
func (wms *WMS) ReadinessQueryString() (string, string, error) {
if hc := wms.Spec.HealthCheck; hc != nil && hc.Querystring != nil {
return *hc.Querystring, *hc.Mimetype, nil
}

firstDataLayerName := ""
for _, layer := range wms.Spec.Service.GetAllLayers() {
if layer.IsDataLayer() {
Expand All @@ -641,8 +662,8 @@ func (wms *WMS) ReadinessQueryString() (string, error) {
}
}
if firstDataLayerName == "" {
return "", errors.New("cannot get readiness probe for WMS, the first datalayer could not be found")
return "", "", errors.New("cannot get readiness probe for WMS, the first datalayer could not be found")
}

return fmt.Sprintf("SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX=%s&CRS=EPSG:28992&WIDTH=100&HEIGHT=100&LAYERS=%s&STYLES=&FORMAT=image/png", wms.HealthCheckBBox(), firstDataLayerName), nil
return fmt.Sprintf("SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX=%s&CRS=EPSG:28992&WIDTH=100&HEIGHT=100&LAYERS=%s&STYLES=&FORMAT=image/png", wms.HealthCheckBBox(), firstDataLayerName), "image/png", nil
}
55 changes: 55 additions & 0 deletions api/v3/zz_generated.deepcopy.go

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

13 changes: 13 additions & 0 deletions config/crd/bases/pdok.nl_wfs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,19 @@ spec:
spec:
description: WFSSpec vertegenwoordigt de hoofdstruct voor de YAML-configuratie
properties:
healthCheck:
description: Custom healthcheck options
properties:
mimetype:
pattern: (image/png|text/xml|text/html)
type: string
querystring:
minLength: 1
type: string
required:
- mimetype
- querystring
type: object
horizontalPodAutoscalerPatch:
description: |-
HorizontalPodAutoscalerPatch - copy of autoscalingv2.HorizontalPodAutoscalerSpec without ScaleTargetRef
Expand Down
40 changes: 40 additions & 0 deletions config/crd/bases/pdok.nl_wms.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,46 @@ spec:
spec:
description: WMSSpec defines the desired state of WMS.
properties:
healthCheck:
description: Custom healthcheck options
properties:
boundingbox:
description: BBox defines a bounding box with coordinates
properties:
maxx:
description: Rechtsonder X coördinaat
pattern: ^-?[0-9]+([.][0-9]*)?$
type: string
maxy:
description: Rechtsonder Y coördinaat
pattern: ^-?[0-9]+([.][0-9]*)?$
type: string
minx:
description: Linksboven X coördinaat
pattern: ^-?[0-9]+([.][0-9]*)?$
type: string
miny:
description: Linksboven Y coördinaat
pattern: ^-?[0-9]+([.][0-9]*)?$
type: string
required:
- maxx
- maxy
- minx
- miny
type: object
mimetype:
pattern: (image/png|text/xml|text/html)
type: string
querystring:
minLength: 1
type: string
type: object
x-kubernetes-validations:
- message: mimetype is required when a querystring is used
rule: '!has(self.querystring) || has(self.mimetype)'
- message: healthcheck should have querystring + mimetype or boundingbox, not both
rule: (has(self.boundingbox) || has(self.querystring)) && !(has(self.querystring) && has(self.boundingbox))
horizontalPodAutoscalerPatch:
description: Optional specification for the HorizontalAutoscaler
properties:
Expand Down
2 changes: 1 addition & 1 deletion internal/controller/ingressroute.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func mutateIngressRoute[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O, ingressRout
tags = append(tags, "inspire")
}

queryString, err := obj.ReadinessQueryString()
queryString, _, err := obj.ReadinessQueryString()
if err != nil {
return err
}
Expand Down
Loading
Loading