diff --git a/charts/internal/seed-controlplane/charts/stackit-blockstorage-csi-driver/values.yaml b/charts/internal/seed-controlplane/charts/stackit-blockstorage-csi-driver/values.yaml
index 60ff609a..02f0e30b 100644
--- a/charts/internal/seed-controlplane/charts/stackit-blockstorage-csi-driver/values.yaml
+++ b/charts/internal/seed-controlplane/charts/stackit-blockstorage-csi-driver/values.yaml
@@ -12,7 +12,6 @@ images:
csi-resizer: image-repository:image-tag
csi-liveness-probe: image-repository:image-tag
csi-snapshot-controller: image-repository:image-tag
- csi-snapshot-validation-webhook: image-repository:image-tag
socketPath: /var/lib/csi/sockets/pluginproxy
region: ""
diff --git a/hack/api-reference/api.md b/hack/api-reference/api.md
index 8bbbc206..6169a6c6 100644
--- a/hack/api-reference/api.md
+++ b/hack/api-reference/api.md
@@ -215,6 +215,17 @@ string
+
+
+compatibilityMode
+
+string
+
+ |
+
+
+ |
+
diff --git a/pkg/apis/stackit/v1alpha1/constants.go b/pkg/apis/stackit/v1alpha1/constants.go
index 86bbdc81..42400ae6 100644
--- a/pkg/apis/stackit/v1alpha1/constants.go
+++ b/pkg/apis/stackit/v1alpha1/constants.go
@@ -5,6 +5,8 @@ package v1alpha1
const (
// DefaultCSIName defines the default CSI (Container Storage Interface) name for STACKIT
DefaultCSIName = "stackit"
+ // DefaultCSICompatibilityMode defines the default CSI driver's compatibility mode.
+ DefaultCSICompatibilityMode = "default"
// DefaultCCMName defines the default CCM (Cloud Controller Manager) controller to use
DefaultCCMName = "stackit"
)
@@ -15,3 +17,11 @@ const (
STACKIT ControllerName = "stackit"
OPENSTACK ControllerName = "openstack"
)
+
+type CSICompatibilityMode string
+
+const (
+ DEFAULT CSICompatibilityMode = "default"
+ COMPAT CSICompatibilityMode = "compat"
+ COMPATBLOCK CSICompatibilityMode = "compatblock"
+)
diff --git a/pkg/apis/stackit/v1alpha1/defaults.go b/pkg/apis/stackit/v1alpha1/defaults.go
index d72cba93..e91caf34 100644
--- a/pkg/apis/stackit/v1alpha1/defaults.go
+++ b/pkg/apis/stackit/v1alpha1/defaults.go
@@ -43,4 +43,7 @@ func SetDefaults_ControlPlaneConfig(obj *ControlPlaneConfig) {
if obj.Storage.CSI.Name == "" {
obj.Storage.CSI.Name = DefaultCSIName
}
+ if obj.Storage.CSI.CompatibilityMode == "" {
+ obj.Storage.CSI.CompatibilityMode = DefaultCSICompatibilityMode
+ }
}
diff --git a/pkg/apis/stackit/v1alpha1/types_controlplane.go b/pkg/apis/stackit/v1alpha1/types_controlplane.go
index 5c10c28a..5b28637d 100644
--- a/pkg/apis/stackit/v1alpha1/types_controlplane.go
+++ b/pkg/apis/stackit/v1alpha1/types_controlplane.go
@@ -58,7 +58,8 @@ type Storage struct {
}
type CSI struct {
- Name string `json:"name"`
+ Name string `json:"name"`
+ CompatibilityMode string `json:"compatibilityMode,omitempty"`
}
// CSIManila contains configuration for CSI Manila driver (support for NFS volumes)
diff --git a/pkg/controller/controlplane/valuesprovider.go b/pkg/controller/controlplane/valuesprovider.go
index 180ac234..af0a341b 100644
--- a/pkg/controller/controlplane/valuesprovider.go
+++ b/pkg/controller/controlplane/valuesprovider.go
@@ -21,10 +21,12 @@ import (
"github.com/gardener/gardener/pkg/apis/core/v1beta1"
v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants"
extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
+ "github.com/gardener/gardener/pkg/chartrenderer"
gardenerutils "github.com/gardener/gardener/pkg/utils"
"github.com/gardener/gardener/pkg/utils/chart"
gutil "github.com/gardener/gardener/pkg/utils/gardener"
kutil "github.com/gardener/gardener/pkg/utils/kubernetes"
+ "github.com/gardener/gardener/pkg/utils/managedresources"
secretutils "github.com/gardener/gardener/pkg/utils/secrets"
secretsmanager "github.com/gardener/gardener/pkg/utils/secrets/manager"
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
@@ -43,6 +45,7 @@ import (
"k8s.io/apimachinery/pkg/types"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
vpaautoscalingv1 "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1"
+ "k8s.io/client-go/rest"
"k8s.io/utils/ptr"
k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/manager"
@@ -359,6 +362,7 @@ var (
func NewValuesProvider(mgr manager.Manager, deployALBIngressController bool, customLabelDomain string) genericactuator.ValuesProvider {
return &valuesProvider{
client: mgr.GetClient(),
+ config: mgr.GetConfig(),
decoder: serializer.NewCodecFactory(mgr.GetScheme(), serializer.EnableStrict).UniversalDecoder(),
deployALBIngressController: deployALBIngressController,
customLabelDomain: customLabelDomain,
@@ -369,6 +373,7 @@ func NewValuesProvider(mgr manager.Manager, deployALBIngressController bool, cus
type valuesProvider struct {
genericactuator.NoopValuesProvider
client k8sclient.Client
+ config *rest.Config
decoder runtime.Decoder
deployALBIngressController bool
customLabelDomain string
@@ -736,6 +741,15 @@ func (vp *valuesProvider) getControlPlaneChartValues(ctx context.Context, cpConf
return nil, err
}
+ maps.Copy(controlPlaneValues, map[string]any{
+ "global": map[string]any{
+ "genericTokenKubeconfigSecretName": extensionscontroller.GenericTokenKubeconfigSecretNameFromCluster(cluster),
+ },
+ openstack.CloudControllerManagerName: ccm,
+ openstack.STACKITCloudControllerManagerName: stackitccm,
+ stackit.PodIdentityWebhookName: podIdentityWebhook,
+ })
+
storageCSIDriver := getCSIDriver(cpConfig)
switch storageCSIDriver {
case stackitv1alpha1.OPENSTACK:
@@ -750,19 +764,17 @@ func (vp *valuesProvider) getControlPlaneChartValues(ctx context.Context, cpConf
controlPlaneValues[openstack.CSIControllerName] = map[string]any{
"enabled": false,
}
+ // TODO: make it nice
+ if getCSICompatibilityMode(cpConfig) == stackitv1alpha1.COMPAT {
+ err := vp.deploySeedCSICompatibilityMode(ctx, cp.GetNamespace(), controlPlaneValues)
+ if err != nil {
+ return nil, fmt.Errorf("failed to deploy CSI CSI compatibility mode: %w", err)
+ }
+ }
default:
return nil, fmt.Errorf("unsupported storage CSI Driver: %s", storageCSIDriver)
}
- maps.Copy(controlPlaneValues, map[string]any{
- "global": map[string]any{
- "genericTokenKubeconfigSecretName": extensionscontroller.GenericTokenKubeconfigSecretNameFromCluster(cluster),
- },
- openstack.CloudControllerManagerName: ccm,
- openstack.STACKITCloudControllerManagerName: stackitccm,
- stackit.PodIdentityWebhookName: podIdentityWebhook,
- })
-
if vp.deployALBIngressController {
fmt.Println("deploying ALB Ingress Controller")
albcm, err := getSTACKITALBCMChartValues(cpConfig, cluster, infra, stackitCredentialsConfig, apiEndpoints, scaledDown, stackitRegion)
@@ -1076,6 +1088,11 @@ func (vp *valuesProvider) getControlPlaneShootChartValues(ctx context.Context, c
case stackitv1alpha1.OPENSTACK:
values[openstack.CSINodeName] = csiNodeDriverValues
values[openstack.CSISTACKITNodeName] = map[string]any{"enabled": false}
+ if getCSICompatibilityMode(cpConfig) == stackitv1alpha1.COMPAT {
+ if err := vp.deployShootCSICompatibilityMode(ctx, cp.Namespace, values); err != nil {
+ return nil, fmt.Errorf("deploy shoot CSI compatibility mode: %w", err)
+ }
+ }
default:
return nil, fmt.Errorf("unsupported CSI driver type: %s", csiDriverInUse)
}
@@ -1176,6 +1193,114 @@ func (vp *valuesProvider) checkEmergencyLoadBalancerAccess(ctx context.Context,
return apiURL, apiToken, nil
}
+func (vp *valuesProvider) deploySeedCSICompatibilityMode(ctx context.Context, namespace string, values map[string]any) error {
+ renderer, err := chartrenderer.NewForConfig(vp.config)
+ if err != nil {
+ return nil
+ }
+
+ // TODO: constant
+ chartName := "stackit-blockstorage-csi-driver"
+
+ // Get the chart Values
+ csiStackitValues := values[openstack.CSISTACKITControllerName].(map[string]any)
+ // Merge csiStackitValues to topLevel. Basically removes the openstack.CSISTACKITControllerName key
+ chartValues := gardenerutils.MergeMaps(values, csiStackitValues)
+ // Override chart values
+ chartValues["prefix"] = "stackit-compat"
+
+ //TODO: Use gardener tools for this? If possible
+ imagesToFind := []string{
+ "csi-driver-stackit",
+ "csi-provisioner",
+ "csi-attacher",
+ "csi-snapshotter",
+ "csi-resizer",
+ "csi-liveness-probe",
+ "csi-snapshot-controller",
+ }
+ images := imagevector.ImageVector()
+ imageMap := make(map[string]any)
+
+ for _, image := range imagesToFind {
+ foundImage, err := images.FindImage(image)
+ if err != nil {
+ return err
+ }
+ imageMap[image] = foundImage.String()
+ }
+ chartValues["images"] = imageMap
+
+ renderedChart, err := renderer.RenderEmbeddedFS(
+ charts.InternalChart,
+ filepath.Join(charts.InternalChartsPath, "seed-controlplane/charts/stackit-blockstorage-csi-driver"),
+ chartName,
+ namespace,
+ chartValues,
+ )
+ if err != nil {
+ return err
+ }
+
+ data := renderedChart.AsSecretData()
+ return managedresources.Create(
+ ctx, vp.client, namespace, "stackit-csi-compat-chart", map[string]string{},
+ false, "seed", data, new(false), nil, new(false),
+ )
+}
+
+func (vp *valuesProvider) deployShootCSICompatibilityMode(ctx context.Context, namespace string, values map[string]any) error {
+ renderer, err := chartrenderer.NewForConfig(vp.config)
+ if err != nil {
+ return err
+ }
+
+ // TODO: constant
+ chartName := "stackit-blockstorage-csi-driver"
+
+ // Get the chart Values
+ csiStackitValues := values[openstack.CSISTACKITControllerName].(map[string]any)
+ // Merge csiStackitValues to topLevel. Basically removes the openstack.CSISTACKITControllerName key
+ chartValues := gardenerutils.MergeMaps(values, csiStackitValues)
+ // Override chart values
+ chartValues["prefix"] = "stackit-compat"
+
+ //TODO: Use gardener tools for this? If possible
+ imagesToFind := []string{
+ "csi-driver-stackit",
+ "csi-node-driver-registrar",
+ "csi-liveness-probe",
+ }
+ images := imagevector.ImageVector()
+ imageMap := make(map[string]any)
+
+ for _, image := range imagesToFind {
+ foundImage, err := images.FindImage(image)
+ if err != nil {
+ return err
+ }
+ imageMap[image] = foundImage.String()
+ }
+ chartValues["images"] = imageMap
+
+ renderedChart, err := renderer.RenderEmbeddedFS(
+ charts.InternalChart,
+ filepath.Join(charts.InternalChartsPath, "shoot-system-components/charts/stackit-blockstorage-csi-driver"),
+ chartName,
+ namespace,
+ chartValues,
+ )
+ if err != nil {
+ return err
+ }
+
+ data := renderedChart.AsSecretData()
+ return managedresources.Create(
+ ctx, vp.client, namespace, "stackit-csi-compat-shoot-chart", map[string]string{},
+ false, "shoot", data, new(false), nil, new(false),
+ )
+}
+
// decodeLoadBalancerAPIEmergencySecret decodes a [corev1.Secret] for emergency loadbalancer access and
// returns the apiURL and apiToken to use or an error.
// The apiURL and apiToken are only set if both values exist inside the secret and are not empty.
@@ -1216,6 +1341,10 @@ func getCSIDriver(cpConfig *stackitv1alpha1.ControlPlaneConfig) stackitv1alpha1.
return stackitv1alpha1.ControllerName(cpConfig.Storage.CSI.Name)
}
+func getCSICompatibilityMode(cpConfig *stackitv1alpha1.ControlPlaneConfig) stackitv1alpha1.CSICompatibilityMode {
+ return stackitv1alpha1.CSICompatibilityMode(cpConfig.Storage.CSI.CompatibilityMode)
+}
+
func getCCMController(cpConfig *stackitv1alpha1.ControlPlaneConfig) stackitv1alpha1.ControllerName {
return stackitv1alpha1.ControllerName(cpConfig.CloudControllerManager.Name)
}