Skip to content

Commit 3ebc401

Browse files
committed
Setup WMS Reconcile
1 parent 5ee4597 commit 3ebc401

File tree

21 files changed

+2389
-703
lines changed

21 files changed

+2389
-703
lines changed

api/v3/shared_types.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,8 @@ func Sha1HashOfName[O WMSWFS](obj O) string {
158158

159159
return hex.EncodeToString(s.Sum(nil))
160160
}
161+
162+
func (o *Options) UseWebserviceProxy() bool {
163+
// options.DisableWebserviceProxy not set or false
164+
return o != nil && (o.DisableWebserviceProxy == nil || !*o.DisableWebserviceProxy)
165+
}

cmd/main.go

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,12 @@ import (
4646
)
4747

4848
const (
49-
defaultMultitoolImage = "docker.io/pdok/docker-multitool:0.9.1"
50-
defaultMapfileGeneratorImage = "docker.io/pdok/mapfile-generator:1.9.3"
51-
defaultCapabilitiesGeneratorImage = "docker.io/pdok/ogc-capabilities-generator:1.0.0-beta5"
52-
defaultFeatureinfoGeneratorImage = "docker.io/pdok/featureinfo-generator:v1.4.0-beta1"
49+
defaultMultitoolImage = "acrpdokprodman.azurecr.io/pdok/docker-multitool:0.9.4"
50+
defaultMapfileGeneratorImage = "acrpdokprodman.azurecr.io/pdok/mapfile-generator:1.9.5"
51+
defaultMapserverImage = "acrpdokprodman.azurecr.io/mirror/docker.io/pdok/mapserver:8.4.0-4-nl"
52+
defaultCapabilitiesGeneratorImage = "acrpdokprodman.azurecr.io/mirror/docker.io/pdok/ogc-capabilities-generator:1.0.0-beta5"
53+
defaultFeatureinfoGeneratorImage = "acrpdokprodman.azurecr.io/mirror/docker.io/pdok/featureinfo-generator:v1.4.0-beta1"
54+
defaultOgcWebserviceProxyImage = "acrpdokprodman.azurecr.io/pdok/ogc-webservice-proxy:0.1.8"
5355
)
5456

5557
var (
@@ -76,10 +78,7 @@ func main() {
7678
var enableHTTP2 bool
7779
var tlsOpts []func(*tls.Config)
7880
var host string
79-
var multitoolImage string
80-
var mapfileGeneratorImage string
81-
var capabilitiesGeneratorImage string
82-
var featureinfoGeneratorImage string
81+
var multitoolImage, mapfileGeneratorImage, mapserverImage, capabilitiesGeneratorImage, featureinfoGeneratorImage, ogcWebserviceProxyImage string
8382
flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+
8483
"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.")
8584
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
@@ -100,8 +99,10 @@ func main() {
10099
flag.StringVar(&host, "baseurl", "", "The host which is used in the mapserver service.")
101100
flag.StringVar(&multitoolImage, "multitool-image", defaultMultitoolImage, "The image to use in the blob download init-container.")
102101
flag.StringVar(&mapfileGeneratorImage, "mapfile-generator-image", defaultMapfileGeneratorImage, "The image to use in the mapfile generator init-container.")
102+
flag.StringVar(&mapserverImage, "mapserver-image", defaultMapserverImage, "The image to use in the mapserver container.")
103103
flag.StringVar(&capabilitiesGeneratorImage, "capabilities-generator-image", defaultCapabilitiesGeneratorImage, "The image to use in the capabilities generator init-container.")
104104
flag.StringVar(&featureinfoGeneratorImage, "featureinfo-generator-image", defaultFeatureinfoGeneratorImage, "The image to use in the featureinfo generator init-container.")
105+
flag.StringVar(&ogcWebserviceProxyImage, "ogc-webservice-proxy-image", defaultOgcWebserviceProxyImage, "The image to use in the ogc webservice proxy container.")
105106

106107
opts := zap.Options{
107108
Development: true,
@@ -231,19 +232,29 @@ func main() {
231232
}
232233

233234
if err = (&controller.WMSReconciler{
234-
Client: mgr.GetClient(),
235-
Scheme: mgr.GetScheme(),
236-
FeatureinfoGeneratorImage: featureinfoGeneratorImage,
235+
Client: mgr.GetClient(),
236+
Scheme: mgr.GetScheme(),
237+
Images: controller.Images{
238+
MultitoolImage: multitoolImage,
239+
MapfileGeneratorImage: mapfileGeneratorImage,
240+
MapserverImage: mapserverImage,
241+
CapabilitiesGeneratorImage: capabilitiesGeneratorImage,
242+
FeatureinfoGeneratorImage: featureinfoGeneratorImage,
243+
OgcWebserviceProxyImage: ogcWebserviceProxyImage,
244+
},
237245
}).SetupWithManager(mgr); err != nil {
238246
setupLog.Error(err, "unable to create controller", "controller", "WMS")
239247
os.Exit(1)
240248
}
241249
if err = (&controller.WFSReconciler{
242-
Client: mgr.GetClient(),
243-
Scheme: mgr.GetScheme(),
244-
MultitoolImage: multitoolImage,
245-
MapfileGeneratorImage: mapfileGeneratorImage,
246-
CapabilitiesGeneratorImage: capabilitiesGeneratorImage,
250+
Client: mgr.GetClient(),
251+
Scheme: mgr.GetScheme(),
252+
Images: controller.Images{
253+
MultitoolImage: multitoolImage,
254+
MapfileGeneratorImage: mapfileGeneratorImage,
255+
MapserverImage: mapserverImage,
256+
CapabilitiesGeneratorImage: capabilitiesGeneratorImage,
257+
},
247258
}).SetupWithManager(mgr); err != nil {
248259
setupLog.Error(err, "unable to create controller", "controller", "WFS")
249260
os.Exit(1)

config/rbac/role.yaml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,29 @@ kind: ClusterRole
44
metadata:
55
name: manager-role
66
rules:
7+
- apiGroups:
8+
- ""
9+
resources:
10+
- configmaps
11+
- services
12+
verbs:
13+
- create
14+
- delete
15+
- get
16+
- list
17+
- update
18+
- watch
19+
- apiGroups:
20+
- apps
21+
resources:
22+
- deployments
23+
verbs:
24+
- create
25+
- delete
26+
- get
27+
- list
28+
- update
29+
- watch
730
- apiGroups:
831
- pdok.nl
932
resources:
@@ -47,3 +70,15 @@ rules:
4770
- get
4871
- patch
4972
- update
73+
- apiGroups:
74+
- traefik.io
75+
resources:
76+
- ingressroutes
77+
- middlewares
78+
verbs:
79+
- create
80+
- delete
81+
- get
82+
- list
83+
- update
84+
- watch

config/samples/v3_wms.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ metadata:
66
app.kubernetes.io/managed-by: kustomize
77
dataset: dataset
88
dataset-owner: owner
9-
service-type: wfs
9+
service-type: wms
1010
service-version: 1.0.0
1111
name: sample-v3
1212
spec:

internal/controller/blobdownload/blob_download.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@ func downloadTiffs(sb *strings.Builder, wms *pdoknlv3.WMS) error {
138138
}
139139

140140
func downloadStylingAssets(sb *strings.Builder, wms *pdoknlv3.WMS) error {
141+
if wms.Spec.Service.StylingAssets == nil { // TODO Is StylingAssets required and should this return an error?
142+
return nil
143+
}
144+
141145
re := regexp.MustCompile(".*\\.(ttf)$")
142146
for _, blobKey := range wms.Spec.Service.StylingAssets.BlobKeys {
143147
fileName, err := getFilenameFromBlobKey(blobKey)

internal/controller/featureinfogenerator/featureinfo_generator.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ import (
44
"encoding/json"
55
"fmt"
66
pdoknlv3 "github.com/pdok/mapserver-operator/api/v3"
7+
"github.com/pdok/mapserver-operator/internal/controller/mapserver"
78
corev1 "k8s.io/api/core/v1"
89
)
910

1011
const (
11-
htmlTemplatesPath = "/srv/data/config/templates"
12-
ConfigMapFeatureinfoGeneratorVolumeName = "featureinfo-generator-config"
12+
htmlTemplatesPath = "/srv/data/config/templates"
1313
)
1414

1515
func GetFeatureinfoGeneratorInitContainer(image string, srvDir string) (*corev1.Container, error) {
@@ -28,7 +28,7 @@ func GetFeatureinfoGeneratorInitContainer(image string, srvDir string) (*corev1.
2828
},
2929
VolumeMounts: []corev1.VolumeMount{
3030
{Name: "base", MountPath: srvDir + "/data", ReadOnly: false},
31-
{Name: ConfigMapFeatureinfoGeneratorVolumeName, MountPath: "/input", ReadOnly: true},
31+
{Name: mapserver.ConfigMapFeatureinfoGeneratorVolumeName, MountPath: "/input", ReadOnly: true},
3232
},
3333
}
3434

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package legendgenerator
2+
3+
import (
4+
pdoknlv3 "github.com/pdok/mapserver-operator/api/v3"
5+
"github.com/pdok/mapserver-operator/internal/controller/mapserver"
6+
corev1 "k8s.io/api/core/v1"
7+
)
8+
9+
func GetLegendGeneratorInitContainer(wms *pdoknlv3.WMS, image string, srvDir string) (*corev1.Container, error) {
10+
initContainer := corev1.Container{
11+
Name: "legend-generator",
12+
Image: image,
13+
ImagePullPolicy: corev1.PullIfNotPresent,
14+
Env: []corev1.EnvVar{mapserver.GetMapfileEnvVar(wms)},
15+
Command: []string{
16+
"bash",
17+
"-c",
18+
`set -eu;
19+
cat /input/input | xargs -n 2 echo | while read layer style; do
20+
echo Generating legend for layer: $layer, style: $style;
21+
mkdir -p /var/www/legend/$layer;
22+
mapserv -nh 'QUERY_STRING=SERVICE=WMS&language=dut&version=1.3.0&service=WMS&request=GetLegendGraphic&sld_version=1.1.0&layer='$layer'&format=image/png&STYLE='$style'' > /var/www/legend/$layer/${style}.png;
23+
done
24+
`,
25+
},
26+
VolumeMounts: []corev1.VolumeMount{
27+
{Name: "base", MountPath: srvDir + "/data", ReadOnly: false},
28+
getDataVolumeMount(),
29+
getConfigVolumeMount(),
30+
},
31+
}
32+
33+
if wms.Spec.Service.Mapfile != nil {
34+
volumeMount := corev1.VolumeMount{
35+
Name: "mapfile",
36+
MountPath: "/srv/data/config/mapfile",
37+
}
38+
initContainer.VolumeMounts = append(initContainer.VolumeMounts, volumeMount)
39+
}
40+
41+
return &initContainer, nil
42+
}
43+
44+
func GetLegendFixerInitContainer(image string) *corev1.Container {
45+
return &corev1.Container{
46+
Name: "legend-fixer",
47+
Image: image,
48+
ImagePullPolicy: corev1.PullIfNotPresent,
49+
Command: []string{
50+
"/bin/bash",
51+
"/input/legend-fixer.sh",
52+
},
53+
VolumeMounts: []corev1.VolumeMount{
54+
getDataVolumeMount(),
55+
getConfigVolumeMount(),
56+
},
57+
}
58+
}
59+
60+
func GetConfigMapData(wms *pdoknlv3.WMS) map[string]string {
61+
data := map[string]string{
62+
"default_mapserver.conf": defaultMapserverConf,
63+
}
64+
65+
addLayerInput(wms, data)
66+
if wms.Spec.Options.RewriteGroupToDataLayers != nil && *wms.Spec.Options.RewriteGroupToDataLayers {
67+
addLegendFixerConfig(wms, data)
68+
}
69+
return data
70+
}
71+
72+
func getDataVolumeMount() corev1.VolumeMount {
73+
return corev1.VolumeMount{Name: "data", MountPath: "/var/www", ReadOnly: false}
74+
}
75+
76+
func getConfigVolumeMount() corev1.VolumeMount {
77+
return corev1.VolumeMount{Name: mapserver.ConfigMapLegendGeneratorVolumeName, MountPath: "/input", ReadOnly: true}
78+
}

internal/controller/legendgenerator/mapper_test.go renamed to internal/controller/legendgenerator/legend_generator_test.go

Lines changed: 10 additions & 24 deletions
Large diffs are not rendered by default.

internal/controller/legendgenerator/mapper.go

Lines changed: 8 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,13 @@ package legendgenerator
33
import (
44
"fmt"
55
pdoknlv3 "github.com/pdok/mapserver-operator/api/v3"
6-
"github.com/pdok/mapserver-operator/internal/controller"
7-
smoothoperatorutils "github.com/pdok/smooth-operator/pkg/util"
8-
corev1 "k8s.io/api/core/v1"
9-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10-
"os"
6+
7+
_ "embed"
118
"sigs.k8s.io/yaml"
129
"strings"
1310
)
1411

12+
// TODO Reuse default_mapserver.conf from static_files?
1513
const (
1614
defaultMapserverConf = `CONFIG
1715
ENV
@@ -21,6 +19,9 @@ END
2119
`
2220
)
2321

22+
//go:embed legend-fixer.sh
23+
var legendFixerScript string
24+
2425
type LegendReference struct {
2526
Layer string `yaml:"layer" json:"layer"`
2627
Style string `yaml:"style" json:"style"`
@@ -30,33 +31,6 @@ type OgcWebserviceProxyConfig struct {
3031
GroupLayers map[string][]string `yaml:"grouplayers" json:"grouplayers"`
3132
}
3233

33-
func getBareConfigMapLegendGenerator(obj metav1.Object) *corev1.ConfigMap {
34-
return &corev1.ConfigMap{
35-
ObjectMeta: metav1.ObjectMeta{
36-
Name: obj.GetName() + "-legend-generator",
37-
Namespace: obj.GetNamespace(),
38-
},
39-
}
40-
}
41-
42-
func GetLegendGeneratorConfigMap(wms *pdoknlv3.WMS) *corev1.ConfigMap {
43-
result := getBareConfigMapLegendGenerator(wms)
44-
labels := controller.AddCommonLabels(wms, smoothoperatorutils.CloneOrEmptyMap(wms.GetLabels()))
45-
result.Labels = labels
46-
47-
result.Immutable = smoothoperatorutils.Pointer(true)
48-
result.Data = map[string]string{}
49-
result.Data["default_mapserver.conf"] = defaultMapserverConf
50-
51-
addLayerInput(wms, result.Data)
52-
53-
if wms.Spec.Options.RewriteGroupToDataLayers != nil && *wms.Spec.Options.RewriteGroupToDataLayers {
54-
addLegendFixerConfig(wms, result.Data)
55-
}
56-
57-
return result
58-
}
59-
6034
func addLayerInput(wms *pdoknlv3.WMS, data map[string]string) {
6135
legendReferences := make([]LegendReference, 0)
6236

@@ -100,10 +74,7 @@ func processLayer(layer *pdoknlv3.Layer, legendReferences *[]LegendReference) {
10074
}
10175

10276
func addLegendFixerConfig(wms *pdoknlv3.WMS, data map[string]string) {
103-
fileBytes, err := os.ReadFile("./legend-fixer.sh")
104-
if err == nil {
105-
data["legend-fixer.sh"] = string(fileBytes)
106-
}
77+
data["legend-fixer.sh"] = legendFixerScript
10778

10879
topLayer := wms.Spec.Service.Layer
10980

@@ -154,7 +125,7 @@ func addLegendFixerConfig(wms *pdoknlv3.WMS, data map[string]string) {
154125
}
155126

156127
ogcWebServiceProxyConfig := OgcWebserviceProxyConfig{GroupLayers: groupLayers}
157-
proxyConfigData, err := yaml.Marshal(ogcWebServiceProxyConfig)
128+
proxyConfigData, _ := yaml.Marshal(ogcWebServiceProxyConfig)
158129
data["ogc-webservice-proxy-config.yaml"] = string(proxyConfigData)
159130
}
160131

0 commit comments

Comments
 (0)