Skip to content

Commit e5fc07f

Browse files
committed
Dynamic PVC selection base on workspace
A backup job now determines the name of pvc based on used storage type. It distinguish between different storage types (common and per-workspace) and mount the volume dynamically. Signed-off-by: Ales Raszka <[email protected]>
1 parent 0f957f2 commit e5fc07f

File tree

2 files changed

+45
-8
lines changed

2 files changed

+45
-8
lines changed

controllers/backupcronjob/backupcronjob_controller.go

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,13 @@ import (
2424
dw "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
2525
controllerv1alpha1 "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
2626
"github.com/devfile/devworkspace-operator/internal/images"
27+
"github.com/devfile/devworkspace-operator/pkg/common"
2728
"github.com/devfile/devworkspace-operator/pkg/conditions"
2829
"github.com/devfile/devworkspace-operator/pkg/config"
30+
wkspConfig "github.com/devfile/devworkspace-operator/pkg/config"
2931
"github.com/devfile/devworkspace-operator/pkg/constants"
3032
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
33+
"github.com/devfile/devworkspace-operator/pkg/provision/storage"
3134
"github.com/go-logr/logr"
3235
"github.com/robfig/cron/v3"
3336
batchv1 "k8s.io/api/batch/v1"
@@ -352,12 +355,18 @@ func (r *BackupCronJobReconciler) createBackupJob(
352355
backUpConfig := dwOperatorConfig.Config.Workspace.BackupCronJob
353356

354357
// Find a PVC with the name "claim-devworkspace" or based on the name from the operator config
355-
pvcName := "claim-devworkspace"
356-
if dwOperatorConfig.Config.Workspace.PVCName != "" {
357-
pvcName = dwOperatorConfig.Config.Workspace.PVCName
358+
pvcName, workspacePath, err := r.getWorkspacePVCName(workspace, dwOperatorConfig, ctx, logger)
359+
if err != nil {
360+
log.Error(err, "Failed to get workspace PVC name", "devworkspace", workspace.Name)
361+
return err
362+
}
363+
if pvcName == "" {
364+
log.Error(err, "No PVC found for DevWorkspace", "id", dwID)
365+
return err
358366
}
367+
359368
pvc := &corev1.PersistentVolumeClaim{}
360-
err := r.Get(ctx, client.ObjectKey{Name: pvcName, Namespace: workspace.Namespace}, pvc)
369+
err = r.Get(ctx, client.ObjectKey{Name: pvcName, Namespace: workspace.Namespace}, pvc)
361370
if err != nil {
362371
log.Error(err, "Failed to get PVC for DevWorkspace", "id", dwID)
363372
return err
@@ -388,7 +397,7 @@ func (r *BackupCronJobReconciler) createBackupJob(
388397
{Name: "WORKSPACE_ID", Value: dwID},
389398
{
390399
Name: "BACKUP_SOURCE_PATH",
391-
Value: "/workspace/" + dwID + "/" + constants.DefaultProjectsSourcesRoot,
400+
Value: "/workspace/" + workspacePath,
392401
},
393402
{Name: "STORAGE_DRIVER", Value: "overlay"},
394403
{Name: "BUILDAH_ISOLATION", Value: "chroot"},
@@ -475,6 +484,32 @@ func (r *BackupCronJobReconciler) createBackupJob(
475484
return nil
476485
}
477486

487+
// getWorkspacePVCName determines the PVC name and workspace path based on the storage provisioner used.
488+
func (r *BackupCronJobReconciler) getWorkspacePVCName(workspace *dw.DevWorkspace, dwOperatorConfig *controllerv1alpha1.DevWorkspaceOperatorConfig, ctx context.Context, logger logr.Logger) (string, string, error) {
489+
config, err := wkspConfig.ResolveConfigForWorkspace(workspace, r.Client)
490+
491+
workspaceWithConfig := &common.DevWorkspaceWithConfig{}
492+
workspaceWithConfig.DevWorkspace = workspace
493+
workspaceWithConfig.Config = config
494+
495+
storageProvisioner, err := storage.GetProvisioner(workspaceWithConfig)
496+
if err != nil {
497+
return "", "", err
498+
}
499+
if _, ok := storageProvisioner.(*storage.PerWorkspaceStorageProvisioner); ok {
500+
pvcName := common.PerWorkspacePVCName(workspace.Status.DevWorkspaceId)
501+
return pvcName, constants.DefaultProjectsSourcesRoot, nil
502+
503+
} else if _, ok := storageProvisioner.(*storage.CommonStorageProvisioner); ok {
504+
pvcName := "claim-devworkspace"
505+
if dwOperatorConfig.Config.Workspace.PVCName != "" {
506+
pvcName = dwOperatorConfig.Config.Workspace.PVCName
507+
}
508+
return pvcName, workspace.Status.DevWorkspaceId + "/" + constants.DefaultProjectsSourcesRoot, nil
509+
}
510+
return "", "", nil
511+
}
512+
478513
func (r *BackupCronJobReconciler) copySecret(workspace *dw.DevWorkspace, ctx context.Context, sourceSecret *corev1.Secret, logger logr.Logger) (namespaceSecret *corev1.Secret, err error) {
479514
log := logger.WithName("copySecret")
480515
existingNamespaceSecret := &corev1.Secret{}

project-backup/workspace-recovery.sh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ set -x
66
: "${DEVWORKSPACE_BACKUP_REGISTRY:?Missing DEVWORKSPACE_BACKUP_REGISTRY}"
77
: "${DEVWORKSPACE_NAMESPACE:?Missing DEVWORKSPACE_NAMESPACE}"
88
: "${DEVWORKSPACE_NAME:?Missing DEVWORKSPACE_NAME}"
9-
: "${PROJECTS_ROOT:?Missing PROJECTS_ROOT}"
109
: "${BACKUP_SOURCE_PATH:?Missing BACKUP_SOURCE_PATH}"
1110

1211
BACKUP_IMAGE="${DEVWORKSPACE_BACKUP_REGISTRY}/backup-${DEVWORKSPACE_NAMESPACE}-${DEVWORKSPACE_NAME}:latest"
@@ -16,6 +15,9 @@ backup() {
1615
local new_image
1716
new_image=$(buildah from scratch)
1817

18+
echo "Backing up workspace from path: $BACKUP_SOURCE_PATH"
19+
ls -la "$BACKUP_SOURCE_PATH"
20+
1921
buildah copy "$new_image" "$BACKUP_SOURCE_PATH" /
2022
buildah config --label DEVWORKSPACE="$DEVWORKSPACE_NAME" "$new_image"
2123
buildah config --label NAMESPACE="$DEVWORKSPACE_NAMESPACE" "$new_image"
@@ -29,8 +31,8 @@ restore() {
2931
local container_name="workspace-restore"
3032

3133
podman create --name "$container_name" "$BACKUP_IMAGE"
32-
rm -rf "${PROJECTS_ROOT:?}"/*
33-
podman cp "$container_name":/. "$PROJECTS_ROOT"
34+
rm -rf "${BACKUP_SOURCE_PATH:?}"/*
35+
podman cp "$container_name":/. "$BACKUP_SOURCE_PATH"
3436
podman rm "$container_name"
3537
}
3638

0 commit comments

Comments
 (0)