Skip to content
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
1480c98
feat(23570): Add controller for workspace backup
Allda Oct 17, 2025
d1a8f94
feat: Create a backup mechanism using Buildah image
Allda Oct 24, 2025
b5bbebd
feat: determine backup need based on LastBackupTime
Allda Oct 29, 2025
307145c
feat: Use PVC name from config if provided
Allda Oct 29, 2025
51b3eec
feat: Allow using registry auth for private registies
Allda Nov 3, 2025
9b0ed96
fix: Use correct repository for backup job
Allda Nov 3, 2025
c282a59
Dynamic PVC selection base on workspace
Allda Nov 3, 2025
aa1053d
Remove unnecessary capabilities from backup Job
Allda Nov 5, 2025
b99674a
Create SA for backup jobs
Allda Nov 5, 2025
9c41684
Replace custom pointer fn with k8s ptr package
Allda Nov 5, 2025
b0f56b3
Address code review comments
Allda Nov 11, 2025
4be0f98
Unify logging in the backup controller
Allda Nov 11, 2025
c4a958c
Move Backup registry to nested struct
Allda Nov 18, 2025
2e99b7e
Per workspace backup SA
Allda Nov 18, 2025
cbc61d8
Run backup job as user 1000
Allda Nov 18, 2025
afacdec
Fix typos and clean code
Allda Nov 19, 2025
efe0538
Extend test to cover wider scope
Allda Nov 19, 2025
3aba677
feat: Replace podmand with oras in backup container
Allda Nov 25, 2025
1e4e3fc
Add licence headers to project-backup files
Allda Nov 28, 2025
142a502
Address Anatolii's comments
Allda Dec 2, 2025
f083043
Use namespace auth pull secret
Allda Dec 2, 2025
6433a76
Fix test with non-existent DWOC
Allda Dec 3, 2025
191bec9
Move context always to a first agument
Allda Dec 3, 2025
9d2b116
Use namespaced registry path for backup
Allda Dec 3, 2025
6af5fb8
Support internal OCP registry
Allda Dec 4, 2025
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
12 changes: 12 additions & 0 deletions .github/workflows/next-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,17 @@ jobs:
quay.io/devfile/project-clone:sha-${{ steps.git-sha.outputs.sha }}
file: ./project-clone/Dockerfile

- name: Build and push
uses: docker/build-push-action@0a97817b6ade9f46837855d676c4cca3a2471fc9 #v4.2.1
with:
context: ./project-backup
push: true
platforms: linux/amd64, linux/arm64, linux/ppc64le, linux/s390x
tags: |
quay.io/devfile/project-backup:next
quay.io/devfile/project-backup:sha-${{ steps.git-sha.outputs.sha }}
file: ./project-backup/Dockerfile

build-next-olm-imgs:
runs-on: ubuntu-latest
needs: build-next-imgs
Expand Down Expand Up @@ -147,6 +158,7 @@ jobs:
export TAG="sha-${{ needs.build-next-imgs.outputs.git-sha }}"
export DEFAULT_DWO_IMG="quay.io/devfile/devworkspace-controller:$TAG"
export PROJECT_CLONE_IMG="quay.io/devfile/project-clone:$TAG"
export PROJECT_BACKUP_IMG="quay.io/devfile/project-backup:$TAG"

# Next builds are not rolled out unless the version is incremented. We want to use semver
# prerelease tags to make sure each new build increments on the previous one, e.g.
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,6 @@ jobs:
-
name: Check if project-clone dockerimage build is working
run: docker build -f ./project-clone/Dockerfile .
-
name: Check if project-backup containerimage build is working
run: docker build -f ./project-backup/Containerfile project-backup/
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export DWO_IMG ?= quay.io/devfile/devworkspace-controller:next
export DWO_BUNDLE_IMG ?= quay.io/devfile/devworkspace-operator-bundle:next
export DWO_INDEX_IMG ?= quay.io/devfile/devworkspace-operator-index:next
export PROJECT_CLONE_IMG ?= quay.io/devfile/project-clone:next
export PROJECT_BACKUP_IMG ?= quay.io/devfile/project-backup:next
export PULL_POLICY ?= Always
export DEFAULT_ROUTING ?= basic
export KUBECONFIG ?= ${HOME}/.kube/config
Expand Down Expand Up @@ -128,6 +129,7 @@ _print_vars:
@echo " DWO_BUNDLE_IMG=$(DWO_BUNDLE_IMG)"
@echo " DWO_INDEX_IMG=$(DWO_INDEX_IMG)"
@echo " PROJECT_CLONE_IMG=$(PROJECT_CLONE_IMG)"
@echo " PROJECT_BACKUP_IMG=$(PROJECT_BACKUP_IMG)"
@echo " PULL_POLICY=$(PULL_POLICY)"
@echo " ROUTING_SUFFIX=$(ROUTING_SUFFIX)"
@echo " DEFAULT_ROUTING=$(DEFAULT_ROUTING)"
Expand Down Expand Up @@ -369,6 +371,7 @@ help: Makefile
@echo 'Supported environment variables:'
@echo ' DWO_IMG - Image used for controller'
@echo ' PROJECT_CLONE_IMG - Image used for project-clone init container'
@echo ' PROJECT_BACKUP_IMG - Image used for project-backup workspace backup container'
@echo ' NAMESPACE - Namespace to use for deploying controller'
@echo ' KUBECONFIG - Kubeconfig which should be used for accessing to the cluster. Currently is: $(KUBECONFIG)'
@echo ' ROUTING_SUFFIX - Cluster routing suffix (e.g. $$(minikube ip).nip.io, apps-crc.testing)'
Expand Down
46 changes: 46 additions & 0 deletions apis/controller/v1alpha1/devworkspaceoperatorconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,38 @@ type CleanupCronJobConfig struct {
Schedule string `json:"schedule,omitempty"`
}

type RegistryConfig struct {
// A registry where backup images are stored. Images are stored
// in {registry}/backup-${DEVWORKSPACE_NAMESPACE}-${DEVWORKSPACE_NAME}
// +kubebuilder:validation:Required
Path string `json:"path,omitempty"`
// AuthSecret is the name of a Kubernetes secret of
// type kubernetes.io/dockerconfigjson.
// The secret is expected to be in the same namespace
// as the DevWorkspaceOperatorCongfig.
// +kubebuilder:validation:Optional
AuthSecret string `json:"authSecret,omitempty"`

// ExtraArgs are additional arguments passed to the oras CLI
// +kubebuilder:validation:Optional
ExtraArgs string `json:"extraArgs,omitempty"`
}

type BackupCronJobConfig struct {
// Enable determines whether backup CronJobs should be created for workspace PVCs.
// Defaults to false if not specified.
// +kubebuilder:validation:Optional
Enable *bool `json:"enable,omitempty"`
// RegistryConfig defines the registry configuration where backup images are stored.
// +kubebuilder:validation:Required
Registry *RegistryConfig `json:"registry,omitempty"`
// Schedule specifies the cron schedule for the backup cron job.
// For example, "0 2 * * *" runs daily at 2 AM.
// +kubebuilder:default:="0 2 * * *"
// +kubebuilder:validation:Optional
Schedule string `json:"schedule,omitempty"`
}

type RoutingConfig struct {
// DefaultRoutingClass specifies the routingClass to be used when a DevWorkspace
// specifies an empty `.spec.routingClass`. Supported routingClasses can be defined
Expand Down Expand Up @@ -189,6 +221,8 @@ type WorkspaceConfig struct {
RuntimeClassName *string `json:"runtimeClassName,omitempty"`
// CleanupCronJobConfig defines configuration options for a cron job that automatically cleans up stale DevWorkspaces.
CleanupCronJob *CleanupCronJobConfig `json:"cleanupCronJob,omitempty"`
// BackupCronJobConfig defines configuration options for a cron job that automatically backs up workspace PVCs.
BackupCronJob *BackupCronJobConfig `json:"backupCronJob,omitempty"`
// PostStartTimeout defines the maximum duration the PostStart hook can run
// before it is automatically failed. This timeout is used for the postStart lifecycle hook
// that is used to run commands in the workspace container. The timeout is specified in seconds.
Expand Down Expand Up @@ -331,14 +365,26 @@ type ConfigmapReference struct {
Namespace string `json:"namespace"`
}

type OperatorConfigurationStatus struct {
// Conditions represent the latest available observations of the OperatorConfiguration's state
Conditions []metav1.Condition `json:"conditions,omitempty"`
// LastBackupTime is the timestamp of the last successful backup. Nil if
// no backup is configured or no backup has yet succeeded.
LastBackupTime *metav1.Time `json:"lastBackupTime,omitempty"`
}

// DevWorkspaceOperatorConfig is the Schema for the devworkspaceoperatorconfigs API
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:path=devworkspaceoperatorconfigs,scope=Namespaced,shortName=dwoc
type DevWorkspaceOperatorConfig struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Config *OperatorConfiguration `json:"config,omitempty"`
// Status represents the current status of the DevWorkspaceOperatorConfig
// automatically managed by the DevWorkspace Operator.
Status *OperatorConfigurationStatus `json:"status,omitempty"`
}

// DevWorkspaceOperatorConfigList contains a list of DevWorkspaceOperatorConfig
Expand Down
77 changes: 77 additions & 0 deletions apis/controller/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 11 additions & 1 deletion build/scripts/generate_deployment.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
set -e

# List of environment variables that will be replaced by envsubst
SUBST_VARS='$NAMESPACE $DWO_IMG $PROJECT_CLONE_IMG $ROUTING_SUFFIX $DEFAULT_ROUTING $PULL_POLICY'
SUBST_VARS='$NAMESPACE $DWO_IMG $PROJECT_CLONE_IMG $PROJECT_BACKUP_IMG $ROUTING_SUFFIX $DEFAULT_ROUTING $PULL_POLICY'

SCRIPT_DIR=$(cd "$(dirname "$0")"; pwd)
DEPLOY_DIR="$SCRIPT_DIR/../../deploy/"
Expand All @@ -58,6 +58,11 @@ Arguments:
'--use-defaults' is passed; otherwise, the value of the PROJECT_CLONE_IMG
environment variable is used. If unspecifed, the default value of
'quay.io/devfile/project-clone:next' is used.
--project-backup-image
Image to use for the project backup workspace. Used only when
'--use-defaults' is passed; otherwise, the value of the PROJECT_BACKUP_IMG
environment variable is used. If unspecifed, the default value of
'quay.io/devfile/project-backup:next' is used.
--split-yaml
Parse output file combined.yaml into a yaml file for each record
in combined yaml. Files are output to the 'objects' subdirectory
Expand Down Expand Up @@ -96,6 +101,10 @@ while [[ "$#" -gt 0 ]]; do
PROJECT_CLONE_IMG=$2
shift
;;
--project-backup-image)
PROJECT_BACKUP_IMG=$2
shift
;;
--split-yamls)
SPLIT_YAMLS=true
;;
Expand All @@ -118,6 +127,7 @@ if $USE_DEFAULT_ENV; then
export NAMESPACE=devworkspace-controller
export DWO_IMG=${DEFAULT_DWO_IMG:-"quay.io/devfile/devworkspace-controller:next"}
export PROJECT_CLONE_IMG=${PROJECT_CLONE_IMG:-"quay.io/devfile/project-clone:next"}
export PROJECT_BACKUP_IMG=${PROJECT_BACKUP_IMG:-"quay.io/devfile/project-backup:next"}
export PULL_POLICY=Always
export DEFAULT_ROUTING=basic
export DEVWORKSPACE_API_VERSION=a6ec0a38307b63a29fad2eea945cc69bee97a683
Expand Down
Loading
Loading