Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -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: ""
Expand Down
11 changes: 11 additions & 0 deletions hack/api-reference/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,17 @@ string
<p></p>
</td>
</tr>
<tr>
<td>
<code>compatibilityMode</code></br>
<em>
string
</em>
</td>
<td>
<p></p>
</td>
</tr>

</tbody>
</table>
Expand Down
10 changes: 10 additions & 0 deletions pkg/apis/stackit/v1alpha1/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand All @@ -15,3 +17,11 @@ const (
STACKIT ControllerName = "stackit"
OPENSTACK ControllerName = "openstack"
)

type CSICompatibilityMode string

const (
DEFAULT CSICompatibilityMode = "default"
COMPAT CSICompatibilityMode = "compat"
COMPATBLOCK CSICompatibilityMode = "compatblock"
)
3 changes: 3 additions & 0 deletions pkg/apis/stackit/v1alpha1/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
3 changes: 2 additions & 1 deletion pkg/apis/stackit/v1alpha1/types_controlplane.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
147 changes: 138 additions & 9 deletions pkg/controller/controlplane/valuesprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand Down Expand Up @@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -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:
Expand All @@ -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)
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)
}
Expand Down