From 44aa6cc1bafd0904e4543c5d7916a76a94b035b3 Mon Sep 17 00:00:00 2001 From: David Kwon Date: Tue, 16 Apr 2024 18:40:12 -0400 Subject: [PATCH 1/3] Provide initcontainer to set up persistent home Signed-off-by: David Kwon --- .../devworkspaceoperatorconfig_types.go | 6 + .../workspace/devworkspace_controller.go | 2 +- pkg/config/defaults.go | 3 +- pkg/config/sync.go | 6 + pkg/constants/constants.go | 4 + pkg/library/home/persistentHome.go | 144 ++++++++++++++++++ 6 files changed, 163 insertions(+), 2 deletions(-) diff --git a/apis/controller/v1alpha1/devworkspaceoperatorconfig_types.go b/apis/controller/v1alpha1/devworkspaceoperatorconfig_types.go index fa33c2622..0ba804ef7 100644 --- a/apis/controller/v1alpha1/devworkspaceoperatorconfig_types.go +++ b/apis/controller/v1alpha1/devworkspaceoperatorconfig_types.go @@ -152,6 +152,12 @@ type PersistentHomeConfig struct { // Must be used with the 'per-user'/'common' or 'per-workspace' storage class in order to take effect. // Disabled by default. Enabled *bool `json:"enabled,omitempty"` + // Determines whether the init container that initializes the persistent home directory should be disabled. + // When the `/home/user` directory is persisted, the init container is used to initialize the directory before + // the workspace starts. If set to true, the init container will not be created. + // This field is not used if the `workspace.persistUserHome.enabled` field is set to false. + // Enabled by default. + DisableInitContainer *bool `json:"disableInitContainer,omitempty"` } type Proxy struct { diff --git a/controllers/workspace/devworkspace_controller.go b/controllers/workspace/devworkspace_controller.go index 720e5c6e2..d62d24bca 100644 --- a/controllers/workspace/devworkspace_controller.go +++ b/controllers/workspace/devworkspace_controller.go @@ -294,7 +294,7 @@ func (r *DevWorkspaceReconciler) Reconcile(ctx context.Context, req ctrl.Request if home.NeedsPersistentHomeDirectory(workspace) { workspaceWithHomeVolume, err := home.AddPersistentHomeVolume(workspace) if err != nil { - reconcileStatus.addWarning(fmt.Sprintf("Info: default persistentHome volume is not being used: %s", err.Error())) + reconcileStatus.addWarning(fmt.Sprintf("Info: unable to setup home persistence: %s", err.Error())) } else { workspace.Spec.Template = *workspaceWithHomeVolume } diff --git a/pkg/config/defaults.go b/pkg/config/defaults.go index 86ce1e8e4..34fe7ff8e 100644 --- a/pkg/config/defaults.go +++ b/pkg/config/defaults.go @@ -44,7 +44,8 @@ var defaultConfig = &v1alpha1.OperatorConfiguration{ PerWorkspace: &perWorkspaceStorageSize, }, PersistUserHome: &v1alpha1.PersistentHomeConfig{ - Enabled: pointer.Bool(false), + Enabled: pointer.Bool(false), + DisableInitContainer: pointer.Bool(false), }, IdleTimeout: "15m", ProgressTimeout: "5m", diff --git a/pkg/config/sync.go b/pkg/config/sync.go index 11632c9e9..c3a84dd89 100644 --- a/pkg/config/sync.go +++ b/pkg/config/sync.go @@ -338,6 +338,9 @@ func mergeConfig(from, to *controller.OperatorConfiguration) { if from.Workspace.PersistUserHome.Enabled != nil { to.Workspace.PersistUserHome.Enabled = from.Workspace.PersistUserHome.Enabled } + if from.Workspace.PersistUserHome.DisableInitContainer != nil { + to.Workspace.PersistUserHome.DisableInitContainer = from.Workspace.PersistUserHome.DisableInitContainer + } } if from.Workspace.DefaultTemplate != nil { templateSpecContentCopy := from.Workspace.DefaultTemplate.DeepCopy() @@ -522,6 +525,9 @@ func GetCurrentConfigString(currConfig *controller.OperatorConfiguration) string if workspace.PersistUserHome.Enabled != nil && *workspace.PersistUserHome.Enabled != *defaultConfig.Workspace.PersistUserHome.Enabled { config = append(config, fmt.Sprintf("workspace.persistUserHome.enabled=%t", *workspace.PersistUserHome.Enabled)) } + if workspace.PersistUserHome.DisableInitContainer != nil && *workspace.PersistUserHome.DisableInitContainer != *defaultConfig.Workspace.PersistUserHome.DisableInitContainer { + config = append(config, fmt.Sprintf("workspace.persistUserHome.disableInitContainer=%t", *workspace.PersistUserHome.DisableInitContainer)) + } } if !reflect.DeepEqual(workspace.PodSecurityContext, defaultConfig.Workspace.PodSecurityContext) { config = append(config, "workspace.podSecurityContext is set") diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index ba760f3f9..a1b162580 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -41,6 +41,10 @@ const ( HomeVolumeName = "persistent-home" + HomeInitComponentName = "init-persistent-home" + + HomeInitEventId = "init-persistent-home" + ServiceAccount = "devworkspace" PVCStorageSize = "10Gi" diff --git a/pkg/library/home/persistentHome.go b/pkg/library/home/persistentHome.go index 5da933a9d..e1b3b8c33 100644 --- a/pkg/library/home/persistentHome.go +++ b/pkg/library/home/persistentHome.go @@ -27,6 +27,24 @@ import ( "github.com/devfile/devworkspace-operator/pkg/constants" ) +const initScript = `(echo "Checking for stow command" +STOW_COMPLETE=/home/user/.stow_completed +if command -v stow &> /dev/null; then + if [ ! -f $STOW_COMPLETE ]; then + echo "Running stow command" + stow . -t /home/user/ -d /home/tooling/ --no-folding -v 2 > /home/user/.stow.log 2>&1 + cp -n /home/tooling/.viminfo /home/user/.viminfo + cp -n /home/tooling/.bashrc /home/user/.bashrc + cp -n /home/tooling/.bash_profile /home/user/.bash_profile + touch $STOW_COMPLETE + else + echo "Stow command already run. If you wish to re-run it, delete $STOW_COMPLETE from the persistent volume and restart the workspace." + fi +else + echo "Stow command not found" +fi) || true +` + // Returns a modified copy of the given DevWorkspace's Template Spec which contains an additional // Devfile volume 'persistentHome' that is mounted to `/home/user/` for every container component defined in the DevWorkspace. // An error is returned if the addition of the 'persistentHome' volume would result @@ -44,6 +62,13 @@ func AddPersistentHomeVolume(workspace *common.DevWorkspaceWithConfig) (*v1alpha Path: constants.HomeUserDirectory, } + if workspace.Config.Workspace.PersistUserHome.DisableInitContainer == nil || !*workspace.Config.Workspace.PersistUserHome.DisableInitContainer { + err := addInitContainer(dwTemplateSpecCopy) + if err != nil { + return nil, fmt.Errorf("failed to add init container for home persistence setup: %w", err) + } + } + dwTemplateSpecCopy.Components = append(dwTemplateSpecCopy.Components, homeVolume) for _, component := range dwTemplateSpecCopy.Components { if component.Container == nil { @@ -95,3 +120,122 @@ func storageStrategySupportsPersistentHome(workspace *common.DevWorkspaceWithCon storageClass := workspace.Spec.Template.Attributes.GetString(constants.DevWorkspaceStorageTypeAttribute, nil) return storageClass != constants.EphemeralStorageClassType } + +func addInitContainer(dwTemplateSpec *v1alpha2.DevWorkspaceTemplateSpec) error { + + if initComponentExists(dwTemplateSpec) { + return fmt.Errorf("component named %s already exists in the devworkspace", constants.HomeInitComponentName) + } + + if initCommandExists(dwTemplateSpec) { + return fmt.Errorf("command with id %s already exists in the devworkspace", constants.HomeInitEventId) + } + + if initEventExists(dwTemplateSpec) { + return fmt.Errorf("event with id %s already exists in the devworkspace", constants.HomeInitEventId) + } + + initContainer := inferInitContainer(dwTemplateSpec) + if initContainer == nil { + return fmt.Errorf("cannot infer initcontainer for home persistence setup") + } + + addInitContainerComponent(dwTemplateSpec, initContainer) + + if dwTemplateSpec.Commands == nil { + dwTemplateSpec.Commands = []v1alpha2.Command{} + } + + if dwTemplateSpec.Events == nil { + dwTemplateSpec.Events = &v1alpha2.Events{} + } + + dwTemplateSpec.Commands = append(dwTemplateSpec.Commands, v1alpha2.Command{ + Id: constants.HomeInitEventId, + CommandUnion: v1alpha2.CommandUnion{ + Apply: &v1alpha2.ApplyCommand{ + Component: constants.HomeInitComponentName, + }, + }, + }) + + dwTemplateSpec.Events.PreStart = append(dwTemplateSpec.Events.PreStart, constants.HomeInitEventId) + + return nil +} + +func initComponentExists(dwTemplateSpec *v1alpha2.DevWorkspaceTemplateSpec) bool { + if dwTemplateSpec.Components == nil { + return false + } + for _, component := range dwTemplateSpec.Components { + if component.Name == constants.HomeInitComponentName { + return true + } + } + return false + +} + +func initCommandExists(dwTemplateSpec *v1alpha2.DevWorkspaceTemplateSpec) bool { + if dwTemplateSpec.Commands == nil { + return false + } + for _, command := range dwTemplateSpec.Commands { + if command.Id == constants.HomeInitEventId { + return true + } + } + return false +} + +func initEventExists(dwTemplateSpec *v1alpha2.DevWorkspaceTemplateSpec) bool { + if dwTemplateSpec.Events == nil { + return false + } + for _, event := range dwTemplateSpec.Events.PreStart { + if event == constants.HomeInitEventId { + return true + } + } + return false + +} + +func addInitContainerComponent(dwTemplateSpec *v1alpha2.DevWorkspaceTemplateSpec, initContainer *v1alpha2.Container) { + initComponent := v1alpha2.Component{ + Name: constants.HomeInitComponentName, + ComponentUnion: v1alpha2.ComponentUnion{ + Container: &v1alpha2.ContainerComponent{ + Container: *initContainer, + }, + }, + } + dwTemplateSpec.Components = append(dwTemplateSpec.Components, initComponent) +} + +func inferInitContainer(dwTemplateSpec *v1alpha2.DevWorkspaceTemplateSpec) *v1alpha2.Container { + var nonImportedComponent v1alpha2.Component + for _, component := range dwTemplateSpec.Components { + if component.Container == nil { + continue + } + + pluginSource := component.Attributes.GetString(constants.PluginSourceAttribute, nil) + if pluginSource == "" || pluginSource == "parent" { + // First non-imported container component is selected + nonImportedComponent = component + break + } + } + + if nonImportedComponent.Name != "" { + image := nonImportedComponent.Container.Image + return &v1alpha2.Container{ + Image: image, + Command: []string{"/bin/sh", "-c"}, + Args: []string{initScript}, + } + } + return nil +} From 77c8002c6f1430f75d63b4ec856549470694c859 Mon Sep 17 00:00:00 2001 From: dkwon17 Date: Fri, 10 May 2024 21:26:00 +0000 Subject: [PATCH 2/3] Update CRDs and resources Signed-off-by: dkwon17 --- apis/controller/v1alpha1/zz_generated.deepcopy.go | 5 +++++ ...ontroller.devfile.io_devworkspaceoperatorconfigs.yaml | 3 +++ deploy/deployment/kubernetes/combined.yaml | 9 +++++++++ ...s.controller.devfile.io.CustomResourceDefinition.yaml | 9 +++++++++ deploy/deployment/openshift/combined.yaml | 9 +++++++++ ...s.controller.devfile.io.CustomResourceDefinition.yaml | 9 +++++++++ ...ontroller.devfile.io_devworkspaceoperatorconfigs.yaml | 9 +++++++++ 7 files changed, 53 insertions(+) diff --git a/apis/controller/v1alpha1/zz_generated.deepcopy.go b/apis/controller/v1alpha1/zz_generated.deepcopy.go index 21a926fd4..ad01e423c 100644 --- a/apis/controller/v1alpha1/zz_generated.deepcopy.go +++ b/apis/controller/v1alpha1/zz_generated.deepcopy.go @@ -383,6 +383,11 @@ func (in *PersistentHomeConfig) DeepCopyInto(out *PersistentHomeConfig) { *out = new(bool) **out = **in } + if in.DisableInitContainer != nil { + in, out := &in.DisableInitContainer, &out.DisableInitContainer + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PersistentHomeConfig. diff --git a/deploy/bundle/manifests/controller.devfile.io_devworkspaceoperatorconfigs.yaml b/deploy/bundle/manifests/controller.devfile.io_devworkspaceoperatorconfigs.yaml index 091f804cb..76e976136 100644 --- a/deploy/bundle/manifests/controller.devfile.io_devworkspaceoperatorconfigs.yaml +++ b/deploy/bundle/manifests/controller.devfile.io_devworkspaceoperatorconfigs.yaml @@ -1568,6 +1568,9 @@ spec: persistUserHome: description: PersistUserHome defines configuration options for persisting the `/home/user/` directory in workspaces. properties: + disableInitContainer: + description: Determines whether the init container that initializes the persistent home directory should be disabled. When the `/home/user` directory is persisted, the init container is used to initialize the directory before the workspace starts. If set to true, the init container will not be created. This field is not used if the `workspace.persistUserHome.enabled` field is set to false. Enabled by default. + type: boolean enabled: description: Determines whether the `/home/user/` directory in workspaces should persist between workspace shutdown and startup. Must be used with the 'per-user'/'common' or 'per-workspace' storage class in order to take effect. Disabled by default. type: boolean diff --git a/deploy/deployment/kubernetes/combined.yaml b/deploy/deployment/kubernetes/combined.yaml index 3ce2527cb..43be05da4 100644 --- a/deploy/deployment/kubernetes/combined.yaml +++ b/deploy/deployment/kubernetes/combined.yaml @@ -2480,6 +2480,15 @@ spec: description: PersistUserHome defines configuration options for persisting the `/home/user/` directory in workspaces. properties: + disableInitContainer: + description: Determines whether the init container that initializes + the persistent home directory should be disabled. When the + `/home/user` directory is persisted, the init container + is used to initialize the directory before the workspace + starts. If set to true, the init container will not be created. + This field is not used if the `workspace.persistUserHome.enabled` + field is set to false. Enabled by default. + type: boolean enabled: description: Determines whether the `/home/user/` directory in workspaces should persist between workspace shutdown diff --git a/deploy/deployment/kubernetes/objects/devworkspaceoperatorconfigs.controller.devfile.io.CustomResourceDefinition.yaml b/deploy/deployment/kubernetes/objects/devworkspaceoperatorconfigs.controller.devfile.io.CustomResourceDefinition.yaml index 96aabf07f..beb5dfd0a 100644 --- a/deploy/deployment/kubernetes/objects/devworkspaceoperatorconfigs.controller.devfile.io.CustomResourceDefinition.yaml +++ b/deploy/deployment/kubernetes/objects/devworkspaceoperatorconfigs.controller.devfile.io.CustomResourceDefinition.yaml @@ -2480,6 +2480,15 @@ spec: description: PersistUserHome defines configuration options for persisting the `/home/user/` directory in workspaces. properties: + disableInitContainer: + description: Determines whether the init container that initializes + the persistent home directory should be disabled. When the + `/home/user` directory is persisted, the init container + is used to initialize the directory before the workspace + starts. If set to true, the init container will not be created. + This field is not used if the `workspace.persistUserHome.enabled` + field is set to false. Enabled by default. + type: boolean enabled: description: Determines whether the `/home/user/` directory in workspaces should persist between workspace shutdown diff --git a/deploy/deployment/openshift/combined.yaml b/deploy/deployment/openshift/combined.yaml index 8bbf51097..dc906de99 100644 --- a/deploy/deployment/openshift/combined.yaml +++ b/deploy/deployment/openshift/combined.yaml @@ -2480,6 +2480,15 @@ spec: description: PersistUserHome defines configuration options for persisting the `/home/user/` directory in workspaces. properties: + disableInitContainer: + description: Determines whether the init container that initializes + the persistent home directory should be disabled. When the + `/home/user` directory is persisted, the init container + is used to initialize the directory before the workspace + starts. If set to true, the init container will not be created. + This field is not used if the `workspace.persistUserHome.enabled` + field is set to false. Enabled by default. + type: boolean enabled: description: Determines whether the `/home/user/` directory in workspaces should persist between workspace shutdown diff --git a/deploy/deployment/openshift/objects/devworkspaceoperatorconfigs.controller.devfile.io.CustomResourceDefinition.yaml b/deploy/deployment/openshift/objects/devworkspaceoperatorconfigs.controller.devfile.io.CustomResourceDefinition.yaml index 96aabf07f..beb5dfd0a 100644 --- a/deploy/deployment/openshift/objects/devworkspaceoperatorconfigs.controller.devfile.io.CustomResourceDefinition.yaml +++ b/deploy/deployment/openshift/objects/devworkspaceoperatorconfigs.controller.devfile.io.CustomResourceDefinition.yaml @@ -2480,6 +2480,15 @@ spec: description: PersistUserHome defines configuration options for persisting the `/home/user/` directory in workspaces. properties: + disableInitContainer: + description: Determines whether the init container that initializes + the persistent home directory should be disabled. When the + `/home/user` directory is persisted, the init container + is used to initialize the directory before the workspace + starts. If set to true, the init container will not be created. + This field is not used if the `workspace.persistUserHome.enabled` + field is set to false. Enabled by default. + type: boolean enabled: description: Determines whether the `/home/user/` directory in workspaces should persist between workspace shutdown diff --git a/deploy/templates/crd/bases/controller.devfile.io_devworkspaceoperatorconfigs.yaml b/deploy/templates/crd/bases/controller.devfile.io_devworkspaceoperatorconfigs.yaml index a29fff8d8..8249d3006 100644 --- a/deploy/templates/crd/bases/controller.devfile.io_devworkspaceoperatorconfigs.yaml +++ b/deploy/templates/crd/bases/controller.devfile.io_devworkspaceoperatorconfigs.yaml @@ -2479,6 +2479,15 @@ spec: description: PersistUserHome defines configuration options for persisting the `/home/user/` directory in workspaces. properties: + disableInitContainer: + description: Determines whether the init container that initializes + the persistent home directory should be disabled. When the + `/home/user` directory is persisted, the init container + is used to initialize the directory before the workspace + starts. If set to true, the init container will not be created. + This field is not used if the `workspace.persistUserHome.enabled` + field is set to false. Enabled by default. + type: boolean enabled: description: Determines whether the `/home/user/` directory in workspaces should persist between workspace shutdown From 5a27b7896851ef73ca565fba2e4b04ef4f8010f6 Mon Sep 17 00:00:00 2001 From: David Kwon Date: Fri, 26 Apr 2024 12:00:38 -0400 Subject: [PATCH 3/3] Update tests Signed-off-by: David Kwon --- .../creates-home-vm-when-enabled.yaml | 1 + ...es-initcontainer-from-first-component.yaml | 82 +++++++++++++++++++ .../creates-initcontainer-when-enabled.yaml | 68 +++++++++++++++ .../noop-if-home-vm-exists.yaml | 1 + .../noop-if-home-vm-name-used.yaml | 1 + .../noop-if-init-command-already-defined.yaml | 29 +++++++ ...oop-if-init-component-already-defined.yaml | 55 +++++++++++++ ...if-init-prestartevent-already-defined.yaml | 19 +++++ .../noop-if-no-components.yaml | 14 ++++ 9 files changed, 270 insertions(+) create mode 100644 pkg/library/home/testdata/persistent-home/creates-initcontainer-from-first-component.yaml create mode 100644 pkg/library/home/testdata/persistent-home/creates-initcontainer-when-enabled.yaml create mode 100644 pkg/library/home/testdata/persistent-home/noop-if-init-command-already-defined.yaml create mode 100644 pkg/library/home/testdata/persistent-home/noop-if-init-component-already-defined.yaml create mode 100644 pkg/library/home/testdata/persistent-home/noop-if-init-prestartevent-already-defined.yaml create mode 100644 pkg/library/home/testdata/persistent-home/noop-if-no-components.yaml diff --git a/pkg/library/home/testdata/persistent-home/creates-home-vm-when-enabled.yaml b/pkg/library/home/testdata/persistent-home/creates-home-vm-when-enabled.yaml index 973ab916d..091700216 100644 --- a/pkg/library/home/testdata/persistent-home/creates-home-vm-when-enabled.yaml +++ b/pkg/library/home/testdata/persistent-home/creates-home-vm-when-enabled.yaml @@ -6,6 +6,7 @@ input: workspace: persistUserHome: enabled: true + disableInitContainer: true workspace: components: - name: testing-container-1 diff --git a/pkg/library/home/testdata/persistent-home/creates-initcontainer-from-first-component.yaml b/pkg/library/home/testdata/persistent-home/creates-initcontainer-from-first-component.yaml new file mode 100644 index 000000000..60b5f8fbd --- /dev/null +++ b/pkg/library/home/testdata/persistent-home/creates-initcontainer-from-first-component.yaml @@ -0,0 +1,82 @@ +name: "Creates init container from the first component when persistUserHome is enabled" + +input: + devworkspaceId: "test-workspaceid" + config: + workspace: + persistUserHome: + enabled: true + workspace: + components: + - name: testing-container-1 + container: + image: testing-image-1 + volumeMounts: + - name: my-defined-volume + path: /my-defined-volume-path + - name: testing-container-2 + container: + image: testing-image-2 + volumeMounts: + - name: my-defined-volume + path: /my-defined-volume-path + - name: my-defined-volume + volume: {} + +output: + workspace: + components: + - name: testing-container-1 + container: + image: testing-image-1 + volumeMounts: + - name: my-defined-volume + path: /my-defined-volume-path + - name: persistent-home + path: /home/user/ + - name: testing-container-2 + container: + image: testing-image-2 + volumeMounts: + - name: my-defined-volume + path: /my-defined-volume-path + - name: persistent-home + path: /home/user/ + - name: my-defined-volume + volume: {} + - name: init-persistent-home + container: + image: testing-image-1 + volumeMounts: + - name: persistent-home + path: /home/user/ + command: + - /bin/sh + - -c + args: + - | + (echo "Checking for stow command" + STOW_COMPLETE=/home/user/.stow_completed + if command -v stow &> /dev/null; then + if [ ! -f $STOW_COMPLETE ]; then + echo "Running stow command" + stow . -t /home/user/ -d /home/tooling/ --no-folding -v 2 > /home/user/.stow.log 2>&1 + cp -n /home/tooling/.viminfo /home/user/.viminfo + cp -n /home/tooling/.bashrc /home/user/.bashrc + cp -n /home/tooling/.bash_profile /home/user/.bash_profile + touch $STOW_COMPLETE + else + echo "Stow command already run. If you wish to re-run it, delete $STOW_COMPLETE from the persistent volume and restart the workspace." + fi + else + echo "Stow command not found" + fi) || true + - name: persistent-home + volume: {} + commands: + - id: init-persistent-home + apply: + component: init-persistent-home + events: + prestart: + - init-persistent-home diff --git a/pkg/library/home/testdata/persistent-home/creates-initcontainer-when-enabled.yaml b/pkg/library/home/testdata/persistent-home/creates-initcontainer-when-enabled.yaml new file mode 100644 index 000000000..13e6a4bfa --- /dev/null +++ b/pkg/library/home/testdata/persistent-home/creates-initcontainer-when-enabled.yaml @@ -0,0 +1,68 @@ +name: "Creates init container when persistUserHome is enabled" + +input: + devworkspaceId: "test-workspaceid" + config: + workspace: + persistUserHome: + enabled: true + workspace: + components: + - name: testing-container-1 + container: + image: testing-image-1 + volumeMounts: + - name: my-defined-volume + path: /my-defined-volume-path + - name: my-defined-volume + volume: {} + +output: + workspace: + components: + - name: testing-container-1 + container: + image: testing-image-1 + volumeMounts: + - name: my-defined-volume + path: /my-defined-volume-path + - name: persistent-home + path: /home/user/ + - name: my-defined-volume + volume: {} + - name: init-persistent-home + container: + image: testing-image-1 + volumeMounts: + - name: persistent-home + path: /home/user/ + command: + - /bin/sh + - -c + args: + - | + (echo "Checking for stow command" + STOW_COMPLETE=/home/user/.stow_completed + if command -v stow &> /dev/null; then + if [ ! -f $STOW_COMPLETE ]; then + echo "Running stow command" + stow . -t /home/user/ -d /home/tooling/ --no-folding -v 2 > /home/user/.stow.log 2>&1 + cp -n /home/tooling/.viminfo /home/user/.viminfo + cp -n /home/tooling/.bashrc /home/user/.bashrc + cp -n /home/tooling/.bash_profile /home/user/.bash_profile + touch $STOW_COMPLETE + else + echo "Stow command already run. If you wish to re-run it, delete $STOW_COMPLETE from the persistent volume and restart the workspace." + fi + else + echo "Stow command not found" + fi) || true + - name: persistent-home + volume: {} + commands: + - id: init-persistent-home + apply: + component: init-persistent-home + events: + prestart: + - init-persistent-home diff --git a/pkg/library/home/testdata/persistent-home/noop-if-home-vm-exists.yaml b/pkg/library/home/testdata/persistent-home/noop-if-home-vm-exists.yaml index 36ba3fb35..dc896b4ab 100644 --- a/pkg/library/home/testdata/persistent-home/noop-if-home-vm-exists.yaml +++ b/pkg/library/home/testdata/persistent-home/noop-if-home-vm-exists.yaml @@ -6,6 +6,7 @@ input: workspace: persistUserHome: enabled: true + disableInitContainer: true workspace: components: - name: testing-container-1 diff --git a/pkg/library/home/testdata/persistent-home/noop-if-home-vm-name-used.yaml b/pkg/library/home/testdata/persistent-home/noop-if-home-vm-name-used.yaml index d7a886cab..5c406d365 100644 --- a/pkg/library/home/testdata/persistent-home/noop-if-home-vm-name-used.yaml +++ b/pkg/library/home/testdata/persistent-home/noop-if-home-vm-name-used.yaml @@ -6,6 +6,7 @@ input: workspace: persistUserHome: enabled: true + disableInitContainer: true workspace: components: - name: testing-container-1 diff --git a/pkg/library/home/testdata/persistent-home/noop-if-init-command-already-defined.yaml b/pkg/library/home/testdata/persistent-home/noop-if-init-command-already-defined.yaml new file mode 100644 index 000000000..e7af9fe45 --- /dev/null +++ b/pkg/library/home/testdata/persistent-home/noop-if-init-command-already-defined.yaml @@ -0,0 +1,29 @@ +name: "Does not create persistent home volume if command with an id of 'init-persistent-home' is already defined" + +input: + devworkspaceId: "test-workspaceid" + config: + workspace: + persistUserHome: + enabled: true + workspace: + components: + - name: testing-container-1 + container: + image: testing-image-1 + commands: + - id: init-persistent-home + apply: + component: testing-container-1 + +output: + error: "failed to add init container for home persistence setup: command with id init-persistent-home already exists in the devworkspace" + workspace: + components: + - name: testing-container-1 + container: + image: testing-image-1 + commands: + - id: init-persistent-home + apply: + component: testing-container-1 diff --git a/pkg/library/home/testdata/persistent-home/noop-if-init-component-already-defined.yaml b/pkg/library/home/testdata/persistent-home/noop-if-init-component-already-defined.yaml new file mode 100644 index 000000000..e56064647 --- /dev/null +++ b/pkg/library/home/testdata/persistent-home/noop-if-init-component-already-defined.yaml @@ -0,0 +1,55 @@ +name: "Does not create persistent home volume if component named 'init-persistent-home' is already defined" + +input: + devworkspaceId: "test-workspaceid" + config: + workspace: + persistUserHome: + enabled: true + workspace: + components: + - name: testing-container-1 + container: + image: testing-image-1 + volumeMounts: + - name: my-defined-volume + path: /my-defined-volume-path + - name: my-defined-volume + volume: {} + - name: init-persistent-home + container: + image: testing-image-1 + command: + - echo helloworld + commands: + - id: init-persistent-home + apply: + component: init-persistent-home + events: + prestart: + - init-persistent-home + +output: + error: "failed to add init container for home persistence setup: component named init-persistent-home already exists in the devworkspace" + workspace: + components: + - name: testing-container-1 + container: + image: testing-image-1 + volumeMounts: + - name: my-defined-volume + path: /my-defined-volume-path + - name: my-defined-volume + volume: {} + - name: init-persistent-home + container: + image: testing-image-1 + command: + - echo helloworld + commands: + - id: init-persistent-home + apply: + component: init-persistent-home + events: + prestart: + - init-persistent-home diff --git a/pkg/library/home/testdata/persistent-home/noop-if-init-prestartevent-already-defined.yaml b/pkg/library/home/testdata/persistent-home/noop-if-init-prestartevent-already-defined.yaml new file mode 100644 index 000000000..33fd9f541 --- /dev/null +++ b/pkg/library/home/testdata/persistent-home/noop-if-init-prestartevent-already-defined.yaml @@ -0,0 +1,19 @@ +name: "Does not create persistent home volume if prestart event with an id of 'init-persistent-home' is already defined" + +input: + devworkspaceId: "test-workspaceid" + config: + workspace: + persistUserHome: + enabled: true + workspace: + events: + prestart: + - init-persistent-home + +output: + error: "failed to add init container for home persistence setup: command with id init-persistent-home already exists in the devworkspace" + workspace: + events: + prestart: + - init-persistent-home diff --git a/pkg/library/home/testdata/persistent-home/noop-if-no-components.yaml b/pkg/library/home/testdata/persistent-home/noop-if-no-components.yaml new file mode 100644 index 000000000..f82bad9c5 --- /dev/null +++ b/pkg/library/home/testdata/persistent-home/noop-if-no-components.yaml @@ -0,0 +1,14 @@ +name: "No op if there are no components" + +input: + devworkspaceId: "test-workspaceid" + config: + workspace: + persistUserHome: + enabled: true + workspace: + components: [] + +output: + workspace: + components: []