diff --git a/apis/controller/v1alpha1/devworkspaceoperatorconfig_types.go b/apis/controller/v1alpha1/devworkspaceoperatorconfig_types.go index 81aa5987e..966b577b6 100644 --- a/apis/controller/v1alpha1/devworkspaceoperatorconfig_types.go +++ b/apis/controller/v1alpha1/devworkspaceoperatorconfig_types.go @@ -196,6 +196,13 @@ type WorkspaceConfig struct { // If not specified or "0", the timeout is disabled. // +kubebuilder:validation:Optional PostStartTimeout string `json:"postStartTimeout,omitempty"` + // Controls whether the Pod uses the host's user namespace. + // If true (or omitted), the Pod runs in the host's user namespace. + // If false, a new user namespace is created for the Pod. + // This field is only used when the UserNamespacesSupport feature is enabled. + // If the feature is disabled, setting this field may cause an endless workspace start loop. + // +kubebuilder:validation:Optional + HostUsers *bool `json:"hostUsers,omitempty"` } type WebhookConfig struct { diff --git a/apis/controller/v1alpha1/zz_generated.deepcopy.go b/apis/controller/v1alpha1/zz_generated.deepcopy.go index b04904319..f31eb7604 100644 --- a/apis/controller/v1alpha1/zz_generated.deepcopy.go +++ b/apis/controller/v1alpha1/zz_generated.deepcopy.go @@ -788,6 +788,11 @@ func (in *WorkspaceConfig) DeepCopyInto(out *WorkspaceConfig) { *out = new(CleanupCronJobConfig) (*in).DeepCopyInto(*out) } + if in.HostUsers != nil { + in, out := &in.HostUsers, &out.HostUsers + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceConfig. diff --git a/deploy/bundle/manifests/controller.devfile.io_devworkspaceoperatorconfigs.yaml b/deploy/bundle/manifests/controller.devfile.io_devworkspaceoperatorconfigs.yaml index b92f9b1e9..bf6eeb646 100644 --- a/deploy/bundle/manifests/controller.devfile.io_devworkspaceoperatorconfigs.yaml +++ b/deploy/bundle/manifests/controller.devfile.io_devworkspaceoperatorconfigs.yaml @@ -2390,6 +2390,14 @@ spec: - Recreate - RollingUpdate type: string + hostUsers: + description: |- + Controls whether the Pod uses the host's user namespace. + If true (or omitted), the Pod runs in the host's user namespace. + If false, a new user namespace is created for the Pod. + This field is only used when the UserNamespacesSupport feature is enabled. + If the feature is disabled, setting this field may cause an endless workspace start loop. + type: boolean idleTimeout: description: |- IdleTimeout determines how long a workspace should sit idle before being diff --git a/deploy/deployment/kubernetes/combined.yaml b/deploy/deployment/kubernetes/combined.yaml index 0a12dd424..bedaf9846 100644 --- a/deploy/deployment/kubernetes/combined.yaml +++ b/deploy/deployment/kubernetes/combined.yaml @@ -2520,6 +2520,14 @@ spec: - Recreate - RollingUpdate type: string + hostUsers: + description: |- + Controls whether the Pod uses the host's user namespace. + If true (or omitted), the Pod runs in the host's user namespace. + If false, a new user namespace is created for the Pod. + This field is only used when the UserNamespacesSupport feature is enabled. + If the feature is disabled, setting this field may cause an endless workspace start loop. + type: boolean idleTimeout: description: |- IdleTimeout determines how long a workspace should sit idle before being 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 857f1ad8c..52460ba60 100644 --- a/deploy/deployment/kubernetes/objects/devworkspaceoperatorconfigs.controller.devfile.io.CustomResourceDefinition.yaml +++ b/deploy/deployment/kubernetes/objects/devworkspaceoperatorconfigs.controller.devfile.io.CustomResourceDefinition.yaml @@ -2520,6 +2520,14 @@ spec: - Recreate - RollingUpdate type: string + hostUsers: + description: |- + Controls whether the Pod uses the host's user namespace. + If true (or omitted), the Pod runs in the host's user namespace. + If false, a new user namespace is created for the Pod. + This field is only used when the UserNamespacesSupport feature is enabled. + If the feature is disabled, setting this field may cause an endless workspace start loop. + type: boolean idleTimeout: description: |- IdleTimeout determines how long a workspace should sit idle before being diff --git a/deploy/deployment/openshift/combined.yaml b/deploy/deployment/openshift/combined.yaml index 5a22cc0da..87b53da4d 100644 --- a/deploy/deployment/openshift/combined.yaml +++ b/deploy/deployment/openshift/combined.yaml @@ -2520,6 +2520,14 @@ spec: - Recreate - RollingUpdate type: string + hostUsers: + description: |- + Controls whether the Pod uses the host's user namespace. + If true (or omitted), the Pod runs in the host's user namespace. + If false, a new user namespace is created for the Pod. + This field is only used when the UserNamespacesSupport feature is enabled. + If the feature is disabled, setting this field may cause an endless workspace start loop. + type: boolean idleTimeout: description: |- IdleTimeout determines how long a workspace should sit idle before being 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 857f1ad8c..52460ba60 100644 --- a/deploy/deployment/openshift/objects/devworkspaceoperatorconfigs.controller.devfile.io.CustomResourceDefinition.yaml +++ b/deploy/deployment/openshift/objects/devworkspaceoperatorconfigs.controller.devfile.io.CustomResourceDefinition.yaml @@ -2520,6 +2520,14 @@ spec: - Recreate - RollingUpdate type: string + hostUsers: + description: |- + Controls whether the Pod uses the host's user namespace. + If true (or omitted), the Pod runs in the host's user namespace. + If false, a new user namespace is created for the Pod. + This field is only used when the UserNamespacesSupport feature is enabled. + If the feature is disabled, setting this field may cause an endless workspace start loop. + type: boolean idleTimeout: description: |- IdleTimeout determines how long a workspace should sit idle before being diff --git a/deploy/templates/crd/bases/controller.devfile.io_devworkspaceoperatorconfigs.yaml b/deploy/templates/crd/bases/controller.devfile.io_devworkspaceoperatorconfigs.yaml index 559680853..45a1869af 100644 --- a/deploy/templates/crd/bases/controller.devfile.io_devworkspaceoperatorconfigs.yaml +++ b/deploy/templates/crd/bases/controller.devfile.io_devworkspaceoperatorconfigs.yaml @@ -2518,6 +2518,14 @@ spec: - Recreate - RollingUpdate type: string + hostUsers: + description: |- + Controls whether the Pod uses the host's user namespace. + If true (or omitted), the Pod runs in the host's user namespace. + If false, a new user namespace is created for the Pod. + This field is only used when the UserNamespacesSupport feature is enabled. + If the feature is disabled, setting this field may cause an endless workspace start loop. + type: boolean idleTimeout: description: |- IdleTimeout determines how long a workspace should sit idle before being diff --git a/pkg/config/defaults.go b/pkg/config/defaults.go index 024a629dd..7a61ee0b8 100644 --- a/pkg/config/defaults.go +++ b/pkg/config/defaults.go @@ -82,6 +82,11 @@ var defaultConfig = &v1alpha1.OperatorConfiguration{ RetainTime: pointer.Int32(2592000), Schedule: "0 0 1 * *", }, + // Do not declare a default value for this field. + // Setting a default leads to an endless reconcile loop when UserNamespacesSupport is disabled, + // because in that case the field is ignored and always set to nil. + // See: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/ + // HostUsers: pointer.Bool(true), }, } diff --git a/pkg/config/sync.go b/pkg/config/sync.go index 3b774f129..76ffd89a5 100644 --- a/pkg/config/sync.go +++ b/pkg/config/sync.go @@ -435,6 +435,10 @@ func mergeConfig(from, to *controller.OperatorConfiguration) { if from.Workspace.PostStartTimeout != "" { to.Workspace.PostStartTimeout = from.Workspace.PostStartTimeout } + + if from.Workspace.HostUsers != nil { + to.Workspace.HostUsers = from.Workspace.HostUsers + } } } @@ -680,6 +684,9 @@ func GetCurrentConfigString(currConfig *controller.OperatorConfiguration) string config = append(config, fmt.Sprintf("workspace.cleanupCronJob.cronJobScript=%s", workspace.CleanupCronJob.Schedule)) } } + if workspace.HostUsers != nil { + config = append(config, fmt.Sprintf("workspace.hostUsers=%t", *workspace.HostUsers)) + } } if currConfig.EnableExperimentalFeatures != nil && *currConfig.EnableExperimentalFeatures { config = append(config, "enableExperimentalFeatures=true") diff --git a/pkg/provision/workspace/deployment.go b/pkg/provision/workspace/deployment.go index 3bf7d6a63..7b51e0a48 100644 --- a/pkg/provision/workspace/deployment.go +++ b/pkg/provision/workspace/deployment.go @@ -211,6 +211,7 @@ func getSpecDeployment( ServiceAccountName: saName, AutomountServiceAccountToken: nil, RuntimeClassName: workspace.Config.Workspace.RuntimeClassName, + HostUsers: workspace.Config.Workspace.HostUsers, }, }, },