Skip to content

Commit

Permalink
Initial implementation
Browse files Browse the repository at this point in the history
Signed-off-by: David Kwon <[email protected]>
  • Loading branch information
dkwon17 committed Apr 17, 2024
1 parent af98666 commit 28795c2
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 0 deletions.
6 changes: 6 additions & 0 deletions apis/controller/v1alpha1/devworkspaceoperatorconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 used.
DisableInitContainer *bool `json:"initContainerEnabled,omitempty"`
// Image is the container image to use for the init container that initializes the persistent home directory.
InitContainer *dw.Container `json:"initContainer,omitempty"`
}

type Proxy struct {
Expand Down
4 changes: 4 additions & 0 deletions pkg/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ const (

HomeVolumeName = "persistent-home"

HomeInitComponentName = "init-persistent-home"

HomeInitEventId = "init-persistent-home"

ServiceAccount = "devworkspace"

PVCStorageSize = "10Gi"
Expand Down
67 changes: 67 additions & 0 deletions pkg/library/home/persistentHome.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import (

// 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.
// This feature assumes that the container image of the first merged container component in the unflattened devfile contains an
// /entrypoint.sh script that initializes persistentHome for the homeVolumeMount PVC.
// An error is returned if the addition of the 'persistentHome' volume would result
// in an invalid DevWorkspace.
func AddPersistentHomeVolume(workspace *common.DevWorkspaceWithConfig) (*v1alpha2.DevWorkspaceTemplateSpec, error) {
Expand All @@ -44,6 +46,10 @@ func AddPersistentHomeVolume(workspace *common.DevWorkspaceWithConfig) (*v1alpha
Path: constants.HomeUserDirectory,
}

if workspace.Config.Workspace.PersistUserHome.DisableInitContainer == nil || !*workspace.Config.Workspace.PersistUserHome.DisableInitContainer {
addInitContainer(dwTemplateSpecCopy, workspace.Config.Workspace.PersistUserHome.InitContainer)
}

dwTemplateSpecCopy.Components = append(dwTemplateSpecCopy.Components, homeVolume)
for _, component := range dwTemplateSpecCopy.Components {
if component.Container == nil {
Expand Down Expand Up @@ -95,3 +101,64 @@ func storageStrategySupportsPersistentHome(workspace *common.DevWorkspaceWithCon
storageClass := workspace.Spec.Template.Attributes.GetString(constants.DevWorkspaceStorageTypeAttribute, nil)
return storageClass != constants.EphemeralStorageClassType
}

func addInitContainer(dwTemplateSpec *v1alpha2.DevWorkspaceTemplateSpec, initContainerFromConfig *v1alpha2.Container) {

initContainerComponent := v1alpha2.Component{
Name: constants.HomeInitComponentName,
}

initContainer := initContainerFromConfig

if initContainer == nil {
initContainer = inferInitContainer(dwTemplateSpec)
}

if initContainer == nil {
return
}

initContainerComponent.ComponentUnion = v1alpha2.ComponentUnion{
Container: &v1alpha2.ContainerComponent{
Container: *initContainer,
},
}

dwTemplateSpec.Components = append(dwTemplateSpec.Components, initContainerComponent)
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)
}

func inferInitContainer(dwTemplateSpec *v1alpha2.DevWorkspaceTemplateSpec) *v1alpha2.Container {
var firstUnflattenedComponent v1alpha2.Component
for _, component := range dwTemplateSpec.Components {
if component.Container == nil {
continue
}

var err error
component.Attributes.Get(constants.MergedContributionsAttribute, &err)
if err == nil {
firstUnflattenedComponent = component
break
}
}

if firstUnflattenedComponent.Name != "" {
image := firstUnflattenedComponent.Container.Image
command := []string{"/bin/sh", "-c", "/entrypoint.sh || true"}

return &v1alpha2.Container{
Image: image,
Command: command,
}
}
return nil
}

0 comments on commit 28795c2

Please sign in to comment.