diff --git a/internal/controller/legendgenerator/legend_generator.go b/internal/controller/legendgenerator/legend_generator.go index 81944a8..f09f201 100644 --- a/internal/controller/legendgenerator/legend_generator.go +++ b/internal/controller/legendgenerator/legend_generator.go @@ -11,7 +11,13 @@ func GetLegendGeneratorInitContainer(wms *pdoknlv3.WMS, image string, srvDir str Name: "legend-generator", Image: image, ImagePullPolicy: corev1.PullIfNotPresent, - Env: []corev1.EnvVar{mapserver.GetMapfileEnvVar(wms)}, + Env: []corev1.EnvVar{ + { + Name: "MAPSERVER_CONFIG_FILE", + Value: "/srv/mapserver/config/default_mapserver.conf", + }, + mapserver.GetMapfileEnvVar(wms), + }, Command: []string{ "bash", "-c", @@ -33,7 +39,6 @@ exit $exit_code; VolumeMounts: []corev1.VolumeMount{ {Name: "base", MountPath: srvDir + "/data", ReadOnly: false}, getDataVolumeMount(), - getConfigVolumeMount(), }, } @@ -45,6 +50,9 @@ exit $exit_code; initContainer.VolumeMounts = append(initContainer.VolumeMounts, volumeMount) } + // Adding config volumemount here to get the same order as in the old ansible operator + initContainer.VolumeMounts = append(initContainer.VolumeMounts, getConfigVolumeMount()) + return &initContainer, nil } diff --git a/internal/controller/mapserver/deployment.go b/internal/controller/mapserver/deployment.go index 999e51c..f23b1b5 100644 --- a/internal/controller/mapserver/deployment.go +++ b/internal/controller/mapserver/deployment.go @@ -85,7 +85,14 @@ func GetVolumesForDeployment[O pdoknlv3.WMSWFS](obj O, configMapNames types.Hash if mapfile := obj.Mapfile(); mapfile != nil { volumes = append(volumes, v1.Volume{ Name: "mapfile", - VolumeSource: newVolumeSource(mapfile.ConfigMapKeyRef.Key), + VolumeSource: newVolumeSource(mapfile.ConfigMapKeyRef.Name), + }) + } + + if obj.Type() == pdoknlv3.ServiceTypeWMS && obj.Options().UseWebserviceProxy() { + volumes = append(volumes, v1.Volume{ + Name: ConfigMapOgcWebserviceProxyVolumeName, + VolumeSource: newVolumeSource(configMapNames.OgcWebserviceProxy), }) } @@ -143,19 +150,14 @@ func GetVolumesForDeployment[O pdoknlv3.WMSWFS](obj O, configMapNames types.Hash // Add mapfilegenerator config and styling-files (if applicable) here to get the same order as the ansible operator // Needed to compare deployments from the ansible operator and this one - volumes = append(volumes, v1.Volume{ - Name: ConfigMapMapfileGeneratorVolumeName, - VolumeSource: newVolumeSource(configMapNames.MapfileGenerator), - }) - if stylingFilesVolume != nil { - volumes = append(volumes, *stylingFilesVolume) - } - - if obj.Type() == pdoknlv3.ServiceTypeWMS && obj.Options().UseWebserviceProxy() { + if obj.Mapfile() == nil { volumes = append(volumes, v1.Volume{ - Name: ConfigMapOgcWebserviceProxyVolumeName, - VolumeSource: newVolumeSource(configMapNames.OgcWebserviceProxy), + Name: ConfigMapMapfileGeneratorVolumeName, + VolumeSource: newVolumeSource(configMapNames.MapfileGenerator), }) + if stylingFilesVolume != nil { + volumes = append(volumes, *stylingFilesVolume) + } } return volumes @@ -316,8 +318,9 @@ func GetResourcesForDeployment[O pdoknlv3.WMSWFS](obj O) v1.ResourceRequirements } ephemeralStorageLimit := mapperutils.EphemeralStorageLimit(obj) - if ephemeralStorageLimit == nil || ephemeralStorageLimit.IsZero() { - ephemeralStorageLimit = smoothoperatorutils.Pointer(resource.MustParse("200M")) + defaultEphemeralStorageLimit := resource.MustParse("200M") + if ephemeralStorageLimit == nil || ephemeralStorageLimit.IsZero() || ephemeralStorageLimit.Value() < defaultEphemeralStorageLimit.Value() { + ephemeralStorageLimit = smoothoperatorutils.Pointer(defaultEphemeralStorageLimit) } resources.Limits[v1.ResourceEphemeralStorage] = *maxResourceVal(ephemeralStorageLimit, ephemeralStorageRequest) } diff --git a/internal/controller/shared_controller.go b/internal/controller/shared_controller.go index 3c2f503..cece2ef 100644 --- a/internal/controller/shared_controller.go +++ b/internal/controller/shared_controller.go @@ -203,7 +203,7 @@ func mutateDeployment[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O, deployment *a deployment.Spec.Template = corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Annotations: smoothoperatorutils.CloneOrEmptyMap(deployment.Spec.Template.GetAnnotations()), + Annotations: annotations, Labels: labels, }, Spec: corev1.PodSpec{ @@ -262,21 +262,24 @@ func getInitContainerForDeployment[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O) initContainers := []corev1.Container{ *blobDownloadInitContainer, *capabilitiesGeneratorInitContainer, - *mapfileGeneratorInitContainer, + } + + if obj.Mapfile() == nil { + initContainers = append(initContainers, *mapfileGeneratorInitContainer) } if wms, ok := any(obj).(*pdoknlv3.WMS); ok { - legendGeneratorInitContainer, err := legendgenerator.GetLegendGeneratorInitContainer(wms, images.MapserverImage, srvDir) + featureInfoInitContainer, err := featureinfogenerator.GetFeatureinfoGeneratorInitContainer(images.FeatureinfoGeneratorImage, srvDir) if err != nil { return nil, err } - initContainers = append(initContainers, *legendGeneratorInitContainer) + initContainers = append(initContainers, *featureInfoInitContainer) - featureInfoInitContainer, err := featureinfogenerator.GetFeatureinfoGeneratorInitContainer(images.FeatureinfoGeneratorImage, srvDir) + legendGeneratorInitContainer, err := legendgenerator.GetLegendGeneratorInitContainer(wms, images.MapserverImage, srvDir) if err != nil { return nil, err } - initContainers = append(initContainers, *featureInfoInitContainer) + initContainers = append(initContainers, *legendGeneratorInitContainer) if wms.Options().RewriteGroupToDataLayers { legendFixerInitContainer := legendgenerator.GetLegendFixerInitContainer(images.MultitoolImage) @@ -300,66 +303,70 @@ func getContainersForDeployment[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O) ([] return nil, err } - containers := []corev1.Container{ - { - Name: MapserverName, - Image: images.MapserverImage, - ImagePullPolicy: corev1.PullIfNotPresent, - Ports: []corev1.ContainerPort{ - { - ContainerPort: 80, - Protocol: corev1.ProtocolTCP, - }, + mapserverContainer := corev1.Container{ + Name: MapserverName, + Image: images.MapserverImage, + ImagePullPolicy: corev1.PullIfNotPresent, + Ports: []corev1.ContainerPort{ + { + ContainerPort: 80, + Protocol: corev1.ProtocolTCP, }, - Env: mapserver.GetEnvVarsForDeployment(obj, blobsSecret.Name), - VolumeMounts: mapserver.GetVolumeMountsForDeployment(obj, srvDir), - Resources: mapserver.GetResourcesForDeployment(obj), - TerminationMessagePolicy: corev1.TerminationMessageReadFile, - TerminationMessagePath: "/dev/termination-log", - LivenessProbe: livenessProbe, - ReadinessProbe: readinessProbe, - StartupProbe: startupProbe, - Lifecycle: &corev1.Lifecycle{ - PreStop: &corev1.LifecycleHandler{ - Exec: &corev1.ExecAction{ - Command: []string{"sleep", "15"}, - }, + }, + Env: mapserver.GetEnvVarsForDeployment(obj, blobsSecret.Name), + VolumeMounts: mapserver.GetVolumeMountsForDeployment(obj, srvDir), + Resources: mapserver.GetResourcesForDeployment(obj), + TerminationMessagePolicy: corev1.TerminationMessageReadFile, + TerminationMessagePath: "/dev/termination-log", + LivenessProbe: livenessProbe, + ReadinessProbe: readinessProbe, + StartupProbe: startupProbe, + Lifecycle: &corev1.Lifecycle{ + PreStop: &corev1.LifecycleHandler{ + Exec: &corev1.ExecAction{ + Command: []string{"sleep", "15"}, }, }, }, - { - Name: "apache-exporter", - Image: images.ApacheExporterImage, - ImagePullPolicy: corev1.PullIfNotPresent, - TerminationMessagePolicy: corev1.TerminationMessageReadFile, - TerminationMessagePath: "/dev/termination-log", - Ports: []corev1.ContainerPort{ - { - ContainerPort: 9117, - Protocol: corev1.ProtocolTCP, - }, + } + + apacheContainer := corev1.Container{ + Name: "apache-exporter", + Image: images.ApacheExporterImage, + ImagePullPolicy: corev1.PullIfNotPresent, + TerminationMessagePolicy: corev1.TerminationMessageReadFile, + TerminationMessagePath: "/dev/termination-log", + Ports: []corev1.ContainerPort{ + { + ContainerPort: 9117, + Protocol: corev1.ProtocolTCP, }, - Args: []string{ - "--scrape_uri=http://localhost/server-status?auto", + }, + Args: []string{ + "--scrape_uri=http://localhost/server-status?auto", + }, + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceMemory: resource.MustParse("48M"), }, - Resources: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceMemory: resource.MustParse("48M"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("0.02"), - }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("0.02"), }, }, } + containers := []corev1.Container{ + mapserverContainer, + apacheContainer, + } if wms, ok := any(obj).(*pdoknlv3.WMS); ok { if wms.Options().UseWebserviceProxy() { ogcWebserviceProxyContainer, err := ogcwebserviceproxy.GetOgcWebserviceProxyContainer(wms, images.OgcWebserviceProxyImage) if err != nil { return nil, err } - containers = append(containers, *ogcWebserviceProxyContainer) + + return append(containers, *ogcWebserviceProxyContainer), nil } } @@ -545,10 +552,10 @@ func getMatchRule[O pdoknlv3.WMSWFS](obj O) string { func getLegendMatchRule(wms *pdoknlv3.WMS) string { host := pdoknlv3.GetHost(false) if strings.Contains(host, "localhost") { - return "Host(`localhost`) && Path(`/" + pdoknlv3.GetBaseURLPath(wms) + "/legend`)" + return "Host(`localhost`) && PathPrefix(`/" + pdoknlv3.GetBaseURLPath(wms) + "/legend`)" } - return "(Host(`localhost`) || Host(`" + host + "`)) && Path(`/" + pdoknlv3.GetBaseURLPath(wms) + "/legend`)" + return "(Host(`localhost`) || Host(`" + host + "`)) && PathPrefix(`/" + pdoknlv3.GetBaseURLPath(wms) + "/legend`)" } func getBareConfigMapMapfileGenerator[O pdoknlv3.WMSWFS](obj O) *corev1.ConfigMap { @@ -659,8 +666,10 @@ func mutateHorizontalPodAutoscaler[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O, } if len(metrics) == 0 { var avgU int32 = 90 - if podSpecPatch != nil && podSpecPatch.Resources != nil && podSpecPatch.Resources.Requests.Cpu() != nil { - avgU = 80 + if podSpecPatch != nil && podSpecPatch.Resources != nil { + if cpu := podSpecPatch.Resources.Requests.Cpu(); cpu != nil && !cpu.IsZero() { + avgU = 80 + } } metrics = append(metrics, autoscalingv2.MetricSpec{ Type: autoscalingv2.ResourceMetricSourceType, @@ -777,12 +786,6 @@ func mutateService[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O, service *corev1. TargetPort: intstr.FromInt32(mapserverPortNr), Protocol: corev1.ProtocolTCP, }, - { - Name: metricPortName, - Port: metricPortNr, - TargetPort: intstr.FromInt32(metricPortNr), - Protocol: corev1.ProtocolTCP, - }, } if obj.Type() == pdoknlv3.ServiceTypeWMS { @@ -794,6 +797,14 @@ func mutateService[R Reconciler, O pdoknlv3.WMSWFS](r R, obj O, service *corev1. } } + // Add port here to get the same port order as the odl ansible operator + ports = append(ports, corev1.ServicePort{ + Name: metricPortName, + Port: metricPortNr, + TargetPort: intstr.FromInt32(metricPortNr), + Protocol: corev1.ProtocolTCP, + }) + service.Spec = corev1.ServiceSpec{ Type: corev1.ServiceTypeClusterIP, ClusterIP: service.Spec.ClusterIP, @@ -1037,7 +1048,7 @@ func createOrUpdateAllForWMSWFS[R Reconciler, O pdoknlv3.WMSWFS](ctx context.Con // end region ConfigMap // region ConfigMap-MapfileGenerator - { + if obj.Mapfile() == nil { configMapMfg := getBareConfigMapMapfileGenerator(obj) if err = mutateConfigMapMapfileGenerator(r, obj, configMapMfg, ownerInfo); err != nil { return operationResults, err @@ -1069,7 +1080,7 @@ func createOrUpdateAllForWMSWFS[R Reconciler, O pdoknlv3.WMSWFS](ctx context.Con // end region ConfigMap-CapabilitiesGenerator // region ConfigMap-BlobDownload - { + if obj.Options().PrefetchData { configMapBd := getBareConfigMapBlobDownload(obj) if err = mutateConfigMapBlobDownload(r, obj, configMapBd); err != nil { return operationResults, err @@ -1159,7 +1170,7 @@ func createOrUpdateAllForWMSWFS[R Reconciler, O pdoknlv3.WMSWFS](ctx context.Con // end region Deployment // region TraefikMiddleware - { + if obj.Options().IncludeIngress { middleware := getBareCorsHeadersMiddleware(obj) operationResults[smoothoperatorutils.GetObjectFullName(reconcilerClient, middleware)], err = controllerutil.CreateOrUpdate(ctx, reconcilerClient, middleware, func() error { return mutateCorsHeadersMiddleware(r, obj, middleware) @@ -1195,7 +1206,7 @@ func createOrUpdateAllForWMSWFS[R Reconciler, O pdoknlv3.WMSWFS](ctx context.Con // end region HorizontalAutoScaler // region IngressRoute - { + if obj.Options().IncludeIngress { ingress := getBareIngressRoute(obj) operationResults[smoothoperatorutils.GetObjectFullName(reconcilerClient, ingress)], err = controllerutil.CreateOrUpdate(ctx, reconcilerClient, ingress, func() error { return mutateIngressRoute(r, obj, ingress) diff --git a/internal/controller/test_manifests/v3_wfs.yaml b/internal/controller/test_manifests/v3_wfs.yaml index 831bfc3..878fadf 100644 --- a/internal/controller/test_manifests/v3_wfs.yaml +++ b/internal/controller/test_manifests/v3_wfs.yaml @@ -36,7 +36,7 @@ spec: options: automaticCasing: true prefetchData: false - includeIngress: false + includeIngress: true service: prefix: "test" url: https://service.pdok.nl/eigenaar/dataset/wfs/1.0.0 diff --git a/internal/controller/test_manifests/v3_wms.yaml b/internal/controller/test_manifests/v3_wms.yaml index 89c52d3..4e31c74 100644 --- a/internal/controller/test_manifests/v3_wms.yaml +++ b/internal/controller/test_manifests/v3_wms.yaml @@ -56,7 +56,6 @@ spec: resolution: defResolution: stylingAssets: - mapfile: layer: name: top-layer-name title: Top "Layer" Title diff --git a/internal/controller/wms_controller_test.go b/internal/controller/wms_controller_test.go index 6d96493..7cfa011 100644 --- a/internal/controller/wms_controller_test.go +++ b/internal/controller/wms_controller_test.go @@ -351,6 +351,7 @@ var _ = Describe("WMS Controller", func() { Expect(legendGeneratorContainer.VolumeMounts).Should(Equal(volumeMounts)) env = []corev1.EnvVar{ + {Name: "MAPSERVER_CONFIG_FILE", Value: "/srv/mapserver/config/default_mapserver.conf", ValueFrom: nil}, {Name: "MS_MAPFILE", Value: "/srv/data/config/mapfile/service.map", ValueFrom: nil}, } Expect(legendGeneratorContainer.Env).Should(Equal(env)) @@ -839,18 +840,18 @@ var _ = Describe("WMS Controller", func() { TargetPort: intstr.FromInt32(80), Protocol: corev1.ProtocolTCP, }, - { - Name: "metric", - Port: 9117, - TargetPort: intstr.FromInt32(9117), - Protocol: corev1.ProtocolTCP, - }, { Name: "ogc-webservice-proxy", Port: 9111, TargetPort: intstr.FromInt32(9111), Protocol: "TCP", }, + { + Name: "metric", + Port: 9117, + TargetPort: intstr.FromInt32(9117), + Protocol: corev1.ProtocolTCP, + }, })) /** @@ -884,7 +885,7 @@ var _ = Describe("WMS Controller", func() { Expect(len(ingressRoute.Spec.Routes)).To(Equal(2)) Expect(ingressRoute.Spec.Routes[0]).To(Equal(traefikiov1alpha1.Route{ Kind: "Rule", - Match: "Host(`localhost`) && Path(`/owner/dataset/wms/1.0.0/legend`)", + Match: "Host(`localhost`) && PathPrefix(`/owner/dataset/wms/1.0.0/legend`)", Middlewares: []traefikiov1alpha1.MiddlewareRef{{Name: wms.GetName() + "-wms-mapserver-headers"}}, Services: []traefikiov1alpha1.Service{{ LoadBalancerSpec: traefikiov1alpha1.LoadBalancerSpec{ @@ -920,7 +921,7 @@ var _ = Describe("WMS Controller", func() { sampleWms, err := getUniqueWMSSample(counter) counter++ - sampleWms.Spec.Service.Mapfile = &pdoknlv3.Mapfile{ConfigMapKeyRef: corev1.ConfigMapKeySelector{Key: "mapfile.map"}} + sampleWms.Spec.Service.Mapfile = &pdoknlv3.Mapfile{ConfigMapKeyRef: corev1.ConfigMapKeySelector{Key: "mapfile.map", LocalObjectReference: corev1.LocalObjectReference{Name: "custom-mapfile"}}} typeNamespacedNameWms.Name = sampleWms.Name Expect(err).NotTo(HaveOccurred()) @@ -939,14 +940,15 @@ var _ = Describe("WMS Controller", func() { volumeMounts := []corev1.VolumeMount{ {Name: "base", MountPath: "/srv/data", ReadOnly: false}, {Name: "data", MountPath: "/var/www", ReadOnly: false}, - {Name: mapserver.ConfigMapLegendGeneratorVolumeName, MountPath: "/input", ReadOnly: true}, {Name: "mapfile", MountPath: "/srv/data/config/mapfile"}, + {Name: mapserver.ConfigMapLegendGeneratorVolumeName, MountPath: "/input", ReadOnly: true}, } legendGeneratorContainer, _ := getInitContainer("legend-generator", deployment) Expect(legendGeneratorContainer.VolumeMounts).Should(Equal(volumeMounts)) env := []corev1.EnvVar{ + {Name: "MAPSERVER_CONFIG_FILE", Value: "/srv/mapserver/config/default_mapserver.conf", ValueFrom: nil}, {Name: "MS_MAPFILE", Value: "/srv/data/config/mapfile/mapfile.map", ValueFrom: nil}, } Expect(legendGeneratorContainer.Env).Should(Equal(env))