Skip to content

Commit 2e12793

Browse files
Merge pull request #63 from PDOK/jd/healthcheck
Healthcheck
2 parents 121f3ae + fb4ab47 commit 2e12793

File tree

15 files changed

+227
-31
lines changed

15 files changed

+227
-31
lines changed

api/v2beta1/shared_conversion.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,6 @@ func NewV2KubernetesObject(lifecycle *shared_model.Lifecycle, podSpecPatch *core
216216
}
217217
}
218218

219-
// TODO - healthcheck
220219
if podSpecPatch != nil {
221220
kub.Resources = &podSpecPatch.Containers[0].Resources
222221
}

api/v2beta1/wfs_conversion.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,19 @@ func (src *WFS) ToV3(dst *pdoknlv3.WFS) error {
6060
dst.Spec.HorizontalPodAutoscalerPatch = ConvertAutoscaling(*src.Spec.Kubernetes.Autoscaling)
6161
}
6262

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

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

69+
if src.Spec.Kubernetes.HealthCheck != nil {
70+
dst.Spec.HealthCheck = &pdoknlv3.HealthCheckWFS{
71+
Querystring: *src.Spec.Kubernetes.HealthCheck.Querystring,
72+
Mimetype: *src.Spec.Kubernetes.HealthCheck.Mimetype,
73+
}
74+
}
75+
7076
service := pdoknlv3.WFSService{
7177
Prefix: src.Spec.General.Dataset,
7278
URL: CreateBaseURL("https://service.pdok.nl", "wfs", src.Spec.General),
@@ -174,6 +180,13 @@ func (dst *WFS) ConvertFrom(srcRaw conversion.Hub) error {
174180

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

183+
if src.Spec.HealthCheck != nil {
184+
dst.Spec.Kubernetes.HealthCheck = &HealthCheck{
185+
Querystring: &src.Spec.HealthCheck.Querystring,
186+
Mimetype: &src.Spec.HealthCheck.Mimetype,
187+
}
188+
}
189+
177190
service := WFSService{
178191
Title: src.Spec.Service.Title,
179192
Abstract: src.Spec.Service.Abstract,

api/v2beta1/wms_conversion.go

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,12 @@ func (src *WMS) ToV3(target *pdoknlv3.WMS) {
6969
dst.Spec.HorizontalPodAutoscalerPatch = ConvertAutoscaling(*src.Spec.Kubernetes.Autoscaling)
7070
}
7171

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

7776
dst.Spec.Options = ConvertOptionsV2ToV3(src.Spec.Options)
77+
dst.Spec.HealthCheck = convertHealthCheckToV3(src.Spec.Kubernetes.HealthCheck)
7878

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

144+
func convertHealthCheckToV3(v2 *HealthCheck) *pdoknlv3.HealthCheckWMS {
145+
if v2 != nil {
146+
switch {
147+
case v2.Querystring != nil:
148+
return &pdoknlv3.HealthCheckWMS{
149+
Querystring: v2.Querystring,
150+
Mimetype: v2.Mimetype,
151+
}
152+
case v2.Boundingbox != nil:
153+
return &pdoknlv3.HealthCheckWMS{
154+
Boundingbox: smoothoperatorutils.Pointer(sharedModel.ExtentToBBox(strings.ReplaceAll(*v2.Boundingbox, ",", " "))),
155+
}
156+
}
157+
}
158+
159+
return nil
160+
}
161+
144162
// ConvertFrom converts the Hub version (v3) to this WMS (v2beta1).
145163
//
146164
//nolint:revive
@@ -154,6 +172,7 @@ func (dst *WMS) ConvertFrom(srcRaw conversion.Hub) error {
154172
dst.Spec.General = LabelsToV2General(src.ObjectMeta.Labels)
155173

156174
dst.Spec.Kubernetes = NewV2KubernetesObject(src.Spec.Lifecycle, src.Spec.PodSpecPatch, src.Spec.HorizontalPodAutoscalerPatch)
175+
dst.Spec.Kubernetes.HealthCheck = convertHealthCheckToV2(src.Spec.HealthCheck)
157176

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

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

262+
func convertHealthCheckToV2(v3 *pdoknlv3.HealthCheckWMS) *HealthCheck {
263+
if v3 != nil {
264+
switch {
265+
case v3.Querystring != nil:
266+
return &HealthCheck{
267+
Querystring: v3.Querystring,
268+
Mimetype: v3.Mimetype,
269+
}
270+
case v3.Boundingbox != nil:
271+
return &HealthCheck{
272+
Boundingbox: smoothoperatorutils.Pointer(strings.ReplaceAll(v3.Boundingbox.ToExtent(), " ", ",")),
273+
}
274+
}
275+
}
276+
277+
return nil
278+
}
279+
243280
func (v2Service WMSService) GetTopLayer() (*WMSLayer, error) {
244281
// Only one layer defined that has data
245282
if len(v2Service.Layers) == 1 && v2Service.Layers[0].Data != nil {

api/v3/shared_types.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,7 @@ type WMSWFS interface {
5050

5151
GeoPackages() []*Gpkg
5252

53-
ReadinessQueryString() (string, error)
54-
55-
// TODO implement healthcheck in CR
56-
// StartUpQueryString() string
57-
// LivenessQueryString() string
53+
ReadinessQueryString() (string, string, error)
5854
}
5955

6056
// Mapfile references a ConfigMap key where an external mapfile is stored.

api/v3/wfs_types.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ type WFSSpec struct {
8282
// TODO omitting the options field or setting an empty value results in incorrect defaulting of the options
8383
Options *Options `json:"options,omitempty"`
8484

85+
// Custom healthcheck options
86+
HealthCheck *HealthCheckWFS `json:"healthCheck,omitempty"`
87+
8588
// service configuration
8689
Service WFSService `json:"service"`
8790
}
@@ -159,6 +162,14 @@ func (s WFSService) KeywordsIncludingInspireKeyword() []string {
159162
return keywords
160163
}
161164

165+
// HealthCheck is the struct with all fields to configure custom healthchecks
166+
type HealthCheckWFS struct {
167+
// +kubebuilder:validation:MinLength:=1
168+
Querystring string `json:"querystring"`
169+
// +kubebuilder:validation:Pattern=(image/png|text/xml|text/html)
170+
Mimetype string `json:"mimetype"`
171+
}
172+
162173
type Bbox struct {
163174
// EXTENT/wfs_extent in mapfile
164175
//nolint:tagliatelle
@@ -278,9 +289,14 @@ func (wfs *WFS) GeoPackages() []*Gpkg {
278289
return gpkgs
279290
}
280291

281-
func (wfs *WFS) ReadinessQueryString() (string, error) {
292+
func (wfs *WFS) ReadinessQueryString() (string, string, error) {
293+
if hc := wfs.Spec.HealthCheck; hc != nil {
294+
return hc.Querystring, hc.Mimetype, nil
295+
}
296+
282297
if len(wfs.Spec.Service.FeatureTypes) == 0 {
283-
return "nil", errors.New("cannot get readiness probe for WFS, featuretypes could not be found")
298+
return "", "", errors.New("cannot get readiness probe for WFS, featuretypes could not be found")
284299
}
285-
return "SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&TYPENAMES=" + wfs.Spec.Service.FeatureTypes[0].Name + "&STARTINDEX=0&COUNT=1", nil
300+
301+
return "SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&TYPENAMES=" + wfs.Spec.Service.FeatureTypes[0].Name + "&STARTINDEX=0&COUNT=1", "text/xml", nil
286302
}

api/v3/wms_types.go

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ type WMSSpec struct {
6666
// TODO omitting the options field or setting an empty value results in incorrect defaulting of the options
6767
Options *Options `json:"options,omitempty"`
6868

69+
// Custom healthcheck options
70+
HealthCheck *HealthCheckWMS `json:"healthCheck,omitempty"`
71+
6972
// Service specification
7073
Service WMSService `json:"service"`
7174
}
@@ -132,6 +135,18 @@ func (wmsService WMSService) KeywordsIncludingInspireKeyword() []string {
132135
return keywords
133136
}
134137

138+
// HealthCheck is the struct with all fields to configure custom healthchecks
139+
// +kubebuilder:validation:XValidation:rule="!has(self.querystring) || has(self.mimetype)",message="mimetype is required when a querystring is used"
140+
// +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"
141+
type HealthCheckWMS struct {
142+
// +kubebuilder:validation:MinLength:=1
143+
Querystring *string `json:"querystring,omitempty"`
144+
// +kubebuilder:validation:Pattern=(image/png|text/xml|text/html)
145+
Mimetype *string `json:"mimetype,omitempty"`
146+
147+
Boundingbox *shared_model.BBox `json:"boundingbox,omitempty"`
148+
}
149+
135150
// +kubebuilder:validation:XValidation:message="Either blobKeys or configMapRefs is required",rule="has(self.blobKeys) || has(self.configMapRefs)"
136151
type StylingAssets struct {
137152
// +kubebuilder:validations:MinItems:=1
@@ -627,12 +642,18 @@ func (wms *WMS) GeoPackages() []*Gpkg {
627642
}
628643

629644
func (wms *WMS) HealthCheckBBox() string {
630-
// TODO make dynamic
645+
if hc := wms.Spec.HealthCheck; hc != nil && hc.Boundingbox != nil {
646+
return strings.ReplaceAll(hc.Boundingbox.ToExtent(), " ", ",")
647+
}
648+
631649
return "190061.4619730016857,462435.5987861062749,202917.7508707302331,473761.6884966178914"
632650
}
633651

634-
func (wms *WMS) ReadinessQueryString() (string, error) {
635-
// TODO implement healthcheck from CR
652+
func (wms *WMS) ReadinessQueryString() (string, string, error) {
653+
if hc := wms.Spec.HealthCheck; hc != nil && hc.Querystring != nil {
654+
return *hc.Querystring, *hc.Mimetype, nil
655+
}
656+
636657
firstDataLayerName := ""
637658
for _, layer := range wms.Spec.Service.GetAllLayers() {
638659
if layer.IsDataLayer() {
@@ -641,8 +662,8 @@ func (wms *WMS) ReadinessQueryString() (string, error) {
641662
}
642663
}
643664
if firstDataLayerName == "" {
644-
return "", errors.New("cannot get readiness probe for WMS, the first datalayer could not be found")
665+
return "", "", errors.New("cannot get readiness probe for WMS, the first datalayer could not be found")
645666
}
646667

647-
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
668+
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
648669
}

api/v3/zz_generated.deepcopy.go

Lines changed: 55 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/pdok.nl_wfs.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,19 @@ spec:
457457
spec:
458458
description: WFSSpec vertegenwoordigt de hoofdstruct voor de YAML-configuratie
459459
properties:
460+
healthCheck:
461+
description: Custom healthcheck options
462+
properties:
463+
mimetype:
464+
pattern: (image/png|text/xml|text/html)
465+
type: string
466+
querystring:
467+
minLength: 1
468+
type: string
469+
required:
470+
- mimetype
471+
- querystring
472+
type: object
460473
horizontalPodAutoscalerPatch:
461474
description: |-
462475
HorizontalPodAutoscalerPatch - copy of autoscalingv2.HorizontalPodAutoscalerSpec without ScaleTargetRef

config/crd/bases/pdok.nl_wms.yaml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,46 @@ spec:
494494
spec:
495495
description: WMSSpec defines the desired state of WMS.
496496
properties:
497+
healthCheck:
498+
description: Custom healthcheck options
499+
properties:
500+
boundingbox:
501+
description: BBox defines a bounding box with coordinates
502+
properties:
503+
maxx:
504+
description: Rechtsonder X coördinaat
505+
pattern: ^-?[0-9]+([.][0-9]*)?$
506+
type: string
507+
maxy:
508+
description: Rechtsonder Y coördinaat
509+
pattern: ^-?[0-9]+([.][0-9]*)?$
510+
type: string
511+
minx:
512+
description: Linksboven X coördinaat
513+
pattern: ^-?[0-9]+([.][0-9]*)?$
514+
type: string
515+
miny:
516+
description: Linksboven Y coördinaat
517+
pattern: ^-?[0-9]+([.][0-9]*)?$
518+
type: string
519+
required:
520+
- maxx
521+
- maxy
522+
- minx
523+
- miny
524+
type: object
525+
mimetype:
526+
pattern: (image/png|text/xml|text/html)
527+
type: string
528+
querystring:
529+
minLength: 1
530+
type: string
531+
type: object
532+
x-kubernetes-validations:
533+
- message: mimetype is required when a querystring is used
534+
rule: '!has(self.querystring) || has(self.mimetype)'
535+
- message: healthcheck should have querystring + mimetype or boundingbox, not both
536+
rule: (has(self.boundingbox) || has(self.querystring)) && !(has(self.querystring) && has(self.boundingbox))
497537
horizontalPodAutoscalerPatch:
498538
description: Optional specification for the HorizontalAutoscaler
499539
properties:

internal/controller/ingressroute.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func mutateIngressRoute[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O, ingressRout
4545
tags = append(tags, "inspire")
4646
}
4747

48-
queryString, err := obj.ReadinessQueryString()
48+
queryString, _, err := obj.ReadinessQueryString()
4949
if err != nil {
5050
return err
5151
}

0 commit comments

Comments
 (0)