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
17 changes: 17 additions & 0 deletions api/v1alpha1/ogcapi_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ type OGCAPISpec struct {
// Optional list of URLs where the service can be reached
// By default only the spec.service.baseUrl is used
IngressRouteURLs smoothoperatormodel.IngressRouteURLs `json:"ingressRouteUrls,omitempty"`

// +optional
VolumeOperatorSpec *VolumeOperatorSpec `json:"volumeOperatorSpec,omitempty"`
}

// +kubebuilder:object:generate=true
Expand Down Expand Up @@ -105,10 +108,24 @@ type OGCAPI struct {
Spec OGCAPISpec `json:"spec,omitempty"`
Status smoothoperatormodel.OperatorStatus `json:"status,omitempty"`

// Deprecated: use spec.volumeOperatorSpec instead. Kept for backward compatibility; when both are
// set, spec.volumeOperatorSpec takes precedence. This field is auto-copied into
// spec.volumeOperatorSpec (via GetVolumeOperatorSpec) when only this one is set.
// +optional
VolumeOperatorSpec *VolumeOperatorSpec `json:"volumeOperatorSpec,omitempty"`
}

// GetVolumeOperatorSpec returns the effective VolumeOperatorSpec for this OGCAPI.
// spec.volumeOperatorSpec takes precedence over the deprecated top-level volumeOperatorSpec;
// if only the deprecated top-level field is set, it is used as a fallback.
func (ogcapi *OGCAPI) GetVolumeOperatorSpec() *VolumeOperatorSpec {
if ogcapi.Spec.VolumeOperatorSpec != nil {
return ogcapi.Spec.VolumeOperatorSpec
}

return ogcapi.VolumeOperatorSpec
}

func (ogcapi *OGCAPI) OperatorStatus() *smoothoperatormodel.OperatorStatus {
return &ogcapi.Status
}
Expand Down
83 changes: 83 additions & 0 deletions api/v1alpha1/ogcapi_types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
MIT License

Copyright (c) 2024 Publieke Dienstverlening op de Kaart

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

package v1alpha1

import (
"testing"

"github.com/stretchr/testify/assert"
)

func Test_OGCAPI_GetVolumeOperatorSpec(t *testing.T) {
specVolumeOperatorSpec := &VolumeOperatorSpec{BlobPrefix: "spec/prefix"}
topLevelVolumeOperatorSpec := &VolumeOperatorSpec{BlobPrefix: "top-level/prefix"}

tests := []struct {
name string
ogcapi OGCAPI
expected *VolumeOperatorSpec
}{
{
name: "neither set",
ogcapi: OGCAPI{},
expected: nil,
},
{
name: "only top-level (deprecated) set",
ogcapi: OGCAPI{
VolumeOperatorSpec: topLevelVolumeOperatorSpec,
},
expected: topLevelVolumeOperatorSpec,
},
{
name: "only spec set",
ogcapi: OGCAPI{
Spec: OGCAPISpec{VolumeOperatorSpec: specVolumeOperatorSpec},
},
expected: specVolumeOperatorSpec,
},
{
name: "both set: spec takes precedence",
ogcapi: OGCAPI{
Spec: OGCAPISpec{VolumeOperatorSpec: specVolumeOperatorSpec},
VolumeOperatorSpec: topLevelVolumeOperatorSpec,
},
expected: specVolumeOperatorSpec,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := tt.ogcapi.GetVolumeOperatorSpec()
if tt.expected == nil {
assert.Nil(t, result)

return
}

assert.Same(t, tt.expected, result)
})
}
}
5 changes: 5 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,11 @@ func (in *OGCAPISpec) DeepCopyInto(out *OGCAPISpec) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.VolumeOperatorSpec != nil {
in, out := &in.VolumeOperatorSpec, &out.VolumeOperatorSpec
*out = new(VolumeOperatorSpec)
**out = **in
}
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OGCAPISpec.
Expand Down
34 changes: 33 additions & 1 deletion config/crd/bases/pdok.nl_ogcapis.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4752,6 +4752,35 @@ spec:
- title
- version
type: object
volumeOperatorSpec:
description: VolumeOperatorSpec defines the way the volumes are managed
properties:
blobDownloadOptions:
properties:
blobConcurrency:
default: 5
type: integer
blockSize:
default: 4194304
type: integer
type: object
blobPrefix:
description: The prefix to use for the blob storage container
(the location of the data)
type: string
storageCapacity:
default: 1Gi
description: 'The storage capacity to request for the volumes
created by the volume operator, min: 1Gi'
type: string
storageClass:
default: managed-premium
description: The storage class to use for the volumes created
by the volume operator, defaults to managed-premium
type: string
required:
- blobPrefix
type: object
required:
- service
type: object
Expand Down Expand Up @@ -4855,7 +4884,10 @@ spec:
type: array
type: object
volumeOperatorSpec:
description: VolumeOperatorSpec defines the way the volumes are managed
description: |-
Deprecated: use spec.volumeOperatorSpec instead. Kept for backward compatibility; when both are
set, spec.volumeOperatorSpec takes precedence. This field is auto-copied into
spec.volumeOperatorSpec (via GetVolumeOperatorSpec) when only this one is set.
properties:
blobDownloadOptions:
properties:
Expand Down
21 changes: 11 additions & 10 deletions internal/controller/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,9 @@ func (r *OGCAPIReconciler) mutateDeployment(ogcAPI *pdoknlv1alpha1.OGCAPI, deplo
deployment.Spec.Template = podTemplateSpec

// set annotations for optional volume-operator, volume operator requires blob-prefix to be set
if ogcAPI.VolumeOperatorSpec != nil && ogcAPI.VolumeOperatorSpec.BlobPrefix != "" {
deployment = addVolumePopulatorToDeployment(deployment, ogcAPI)
volumeOperatorSpec := ogcAPI.GetVolumeOperatorSpec()
if volumeOperatorSpec != nil && volumeOperatorSpec.BlobPrefix != "" {
deployment = addVolumePopulatorToDeployment(deployment, volumeOperatorSpec)
}

if err := smoothoperatorutil.EnsureSetGVK(r.Client, deployment, deployment); err != nil {
Expand All @@ -136,18 +137,18 @@ func (r *OGCAPIReconciler) mutateDeployment(ogcAPI *pdoknlv1alpha1.OGCAPI, deplo
return controllerruntime.SetControllerReference(ogcAPI, deployment, r.Scheme)
}

func addVolumePopulatorToDeployment(deployment *appsv1.Deployment, ogcAPI *pdoknlv1alpha1.OGCAPI) *appsv1.Deployment {
func addVolumePopulatorToDeployment(deployment *appsv1.Deployment, volumeOperatorSpec *pdoknlv1alpha1.VolumeOperatorSpec) *appsv1.Deployment {
hash := smoothoperatorutil.GenerateHashFromStrings([]string{
ogcAPI.VolumeOperatorSpec.BlobPrefix,
volumeOperatorSpec.BlobPrefix,
volumeMountPath,
ogcAPI.VolumeOperatorSpec.StorageCapacity,
volumeOperatorSpec.StorageCapacity,
})
deployment.Annotations = smoothoperatorutil.CloneOrEmptyMap(deployment.Annotations)
deployment.Annotations["volume-operator.pdok.nl/blob-prefix"] = ogcAPI.VolumeOperatorSpec.BlobPrefix
deployment.Annotations["volume-operator.pdok.nl/blob-prefix"] = volumeOperatorSpec.BlobPrefix
deployment.Annotations["volume-operator.pdok.nl/volume-path"] = volumeMountPath
deployment.Annotations["volume-operator.pdok.nl/storage-class"] = ogcAPI.VolumeOperatorSpec.StorageClass
deployment.Annotations["volume-operator.pdok.nl/storage-class"] = volumeOperatorSpec.StorageClass
deployment.Annotations["volume-operator.pdok.nl/resource-suffix"] = hash
deployment.Annotations["volume-operator.pdok.nl/storage-capacity"] = ogcAPI.VolumeOperatorSpec.StorageCapacity
deployment.Annotations["volume-operator.pdok.nl/storage-capacity"] = volumeOperatorSpec.StorageCapacity

volume := corev1.Volume{
Name: gokoalaName + "-clone",
Expand All @@ -158,10 +159,10 @@ func addVolumePopulatorToDeployment(deployment *appsv1.Deployment, ogcAPI *pdokn
AccessModes: []corev1.PersistentVolumeAccessMode{
corev1.ReadWriteOnce,
},
StorageClassName: &ogcAPI.VolumeOperatorSpec.StorageClass,
StorageClassName: &volumeOperatorSpec.StorageClass,
Resources: corev1.VolumeResourceRequirements{
Requests: corev1.ResourceList{
corev1.ResourceStorage: resource.MustParse(ogcAPI.VolumeOperatorSpec.StorageCapacity),
corev1.ResourceStorage: resource.MustParse(volumeOperatorSpec.StorageCapacity),
},
},
DataSource: &corev1.TypedLocalObjectReference{
Expand Down
Loading