From 14dbb312757de445b5906ef8913f661785298ceb Mon Sep 17 00:00:00 2001 From: Angel Misevski Date: Fri, 17 Sep 2021 17:04:20 -0400 Subject: [PATCH 1/4] Add startProgressTimeout config setting Add setting workspace.startProgressTimeout to denote maximum duration for any workspace phase before the workspace start is failed. Default value is 5m Signed-off-by: Angel Misevski --- .../v1alpha1/devworkspaceoperatorconfig_types.go | 5 +++++ pkg/config/defaults.go | 7 ++++--- pkg/config/sync.go | 3 +++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/apis/controller/v1alpha1/devworkspaceoperatorconfig_types.go b/apis/controller/v1alpha1/devworkspaceoperatorconfig_types.go index 3993ddf25..35a393e55 100644 --- a/apis/controller/v1alpha1/devworkspaceoperatorconfig_types.go +++ b/apis/controller/v1alpha1/devworkspaceoperatorconfig_types.go @@ -61,6 +61,11 @@ type WorkspaceConfig struct { // requires support in the workspace being started. If not specified, the default // value of "15m" is used. IdleTimeout string `json:"idleTimeout,omitempty"` + // StartProgressTimeout determines the maximum duration a DevWorkspace can be in + // a "Starting" phase without progressing before it is automatically failed. + // Duration should be specified in a format parseable by Go's time package, e.g. + // "15m", "20s", "1h30m", etc. If not specified, the default value of "5m" is used. + StartProgressTimeout string `json:"startProgressTimeout,omitempty"` // IgnoredUnrecoverableEvents defines a list of Kubernetes event names that should // be ignored when deciding to fail a DevWorkspace startup. This option should be used // if a transient cluster issue is triggering false-positives (for example, if diff --git a/pkg/config/defaults.go b/pkg/config/defaults.go index 567a82bdf..245146415 100644 --- a/pkg/config/defaults.go +++ b/pkg/config/defaults.go @@ -21,8 +21,9 @@ var DefaultConfig = &v1alpha1.OperatorConfiguration{ ClusterHostSuffix: "", // is auto discovered when running on OpenShift. Must be defined by CR on Kubernetes. }, Workspace: &v1alpha1.WorkspaceConfig{ - ImagePullPolicy: "Always", - PVCName: "claim-devworkspace", - IdleTimeout: "15m", + ImagePullPolicy: "Always", + PVCName: "claim-devworkspace", + IdleTimeout: "15m", + StartProgressTimeout: "5m", }, } diff --git a/pkg/config/sync.go b/pkg/config/sync.go index 1cfc96037..6bda7553e 100644 --- a/pkg/config/sync.go +++ b/pkg/config/sync.go @@ -205,6 +205,9 @@ func mergeConfig(from, to *controller.OperatorConfiguration) { if from.Workspace.IdleTimeout != "" { to.Workspace.IdleTimeout = from.Workspace.IdleTimeout } + if from.Workspace.StartProgressTimeout != "" { + to.Workspace.StartProgressTimeout = from.Workspace.StartProgressTimeout + } if from.Workspace.IgnoredUnrecoverableEvents != nil { to.Workspace.IgnoredUnrecoverableEvents = from.Workspace.IgnoredUnrecoverableEvents } From bc0d35a604706a2da1537fc291c2a6f239eeb4b6 Mon Sep 17 00:00:00 2001 From: Angel Misevski Date: Fri, 17 Sep 2021 17:05:21 -0400 Subject: [PATCH 2/4] Regenerate templates to include startProgressTimeout config Signed-off-by: Angel Misevski --- ...controller.devfile.io_devworkspaceoperatorconfigs.yaml | 3 +++ deploy/deployment/kubernetes/combined.yaml | 8 ++++++++ ...gs.controller.devfile.io.CustomResourceDefinition.yaml | 8 ++++++++ deploy/deployment/openshift/combined.yaml | 8 ++++++++ ...gs.controller.devfile.io.CustomResourceDefinition.yaml | 8 ++++++++ ...controller.devfile.io_devworkspaceoperatorconfigs.yaml | 8 ++++++++ 6 files changed, 43 insertions(+) diff --git a/deploy/bundle/manifests/controller.devfile.io_devworkspaceoperatorconfigs.yaml b/deploy/bundle/manifests/controller.devfile.io_devworkspaceoperatorconfigs.yaml index b07a9f267..431988dd9 100644 --- a/deploy/bundle/manifests/controller.devfile.io_devworkspaceoperatorconfigs.yaml +++ b/deploy/bundle/manifests/controller.devfile.io_devworkspaceoperatorconfigs.yaml @@ -66,6 +66,9 @@ spec: maxLength: 63 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string + startProgressTimeout: + description: StartProgressTimeout determines the maximum duration a DevWorkspace can be in a "Starting" phase without progressing before it is automatically failed. Duration should be specified in a format parseable by Go's time package, e.g. "15m", "20s", "1h30m", etc. If not specified, the default value of "5m" is used. + type: string storageClassName: description: StorageClassName defines and optional storageClass to use for persistent volume claims created to support DevWorkspaces type: string diff --git a/deploy/deployment/kubernetes/combined.yaml b/deploy/deployment/kubernetes/combined.yaml index 1a59b5866..2e729346b 100644 --- a/deploy/deployment/kubernetes/combined.yaml +++ b/deploy/deployment/kubernetes/combined.yaml @@ -95,6 +95,14 @@ spec: maxLength: 63 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string + startProgressTimeout: + description: StartProgressTimeout determines the maximum duration + a DevWorkspace can be in a "Starting" phase without progressing + before it is automatically failed. Duration should be specified + in a format parseable by Go's time package, e.g. "15m", "20s", + "1h30m", etc. If not specified, the default value of "5m" is + used. + type: string storageClassName: description: StorageClassName defines and optional storageClass to use for persistent volume claims created to support DevWorkspaces 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 06b64e713..8c633f434 100644 --- a/deploy/deployment/kubernetes/objects/devworkspaceoperatorconfigs.controller.devfile.io.CustomResourceDefinition.yaml +++ b/deploy/deployment/kubernetes/objects/devworkspaceoperatorconfigs.controller.devfile.io.CustomResourceDefinition.yaml @@ -95,6 +95,14 @@ spec: maxLength: 63 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string + startProgressTimeout: + description: StartProgressTimeout determines the maximum duration + a DevWorkspace can be in a "Starting" phase without progressing + before it is automatically failed. Duration should be specified + in a format parseable by Go's time package, e.g. "15m", "20s", + "1h30m", etc. If not specified, the default value of "5m" is + used. + type: string storageClassName: description: StorageClassName defines and optional storageClass to use for persistent volume claims created to support DevWorkspaces diff --git a/deploy/deployment/openshift/combined.yaml b/deploy/deployment/openshift/combined.yaml index c51a8b9af..670f262a5 100644 --- a/deploy/deployment/openshift/combined.yaml +++ b/deploy/deployment/openshift/combined.yaml @@ -95,6 +95,14 @@ spec: maxLength: 63 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string + startProgressTimeout: + description: StartProgressTimeout determines the maximum duration + a DevWorkspace can be in a "Starting" phase without progressing + before it is automatically failed. Duration should be specified + in a format parseable by Go's time package, e.g. "15m", "20s", + "1h30m", etc. If not specified, the default value of "5m" is + used. + type: string storageClassName: description: StorageClassName defines and optional storageClass to use for persistent volume claims created to support DevWorkspaces 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 06b64e713..8c633f434 100644 --- a/deploy/deployment/openshift/objects/devworkspaceoperatorconfigs.controller.devfile.io.CustomResourceDefinition.yaml +++ b/deploy/deployment/openshift/objects/devworkspaceoperatorconfigs.controller.devfile.io.CustomResourceDefinition.yaml @@ -95,6 +95,14 @@ spec: maxLength: 63 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string + startProgressTimeout: + description: StartProgressTimeout determines the maximum duration + a DevWorkspace can be in a "Starting" phase without progressing + before it is automatically failed. Duration should be specified + in a format parseable by Go's time package, e.g. "15m", "20s", + "1h30m", etc. If not specified, the default value of "5m" is + used. + type: string storageClassName: description: StorageClassName defines and optional storageClass to use for persistent volume claims created to support DevWorkspaces diff --git a/deploy/templates/crd/bases/controller.devfile.io_devworkspaceoperatorconfigs.yaml b/deploy/templates/crd/bases/controller.devfile.io_devworkspaceoperatorconfigs.yaml index 86ff51284..e0c3a4353 100644 --- a/deploy/templates/crd/bases/controller.devfile.io_devworkspaceoperatorconfigs.yaml +++ b/deploy/templates/crd/bases/controller.devfile.io_devworkspaceoperatorconfigs.yaml @@ -94,6 +94,14 @@ spec: maxLength: 63 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string + startProgressTimeout: + description: StartProgressTimeout determines the maximum duration + a DevWorkspace can be in a "Starting" phase without progressing + before it is automatically failed. Duration should be specified + in a format parseable by Go's time package, e.g. "15m", "20s", + "1h30m", etc. If not specified, the default value of "5m" is + used. + type: string storageClassName: description: StorageClassName defines and optional storageClass to use for persistent volume claims created to support DevWorkspaces From cda34d67557a32d77cc850e3da0dce9374cf6f33 Mon Sep 17 00:00:00 2001 From: Angel Misevski Date: Tue, 21 Sep 2021 15:08:04 -0400 Subject: [PATCH 3/4] Fail workspace startup if any phase takes longer than timeout Signed-off-by: Angel Misevski --- .../workspace/devworkspace_controller.go | 24 ++++++++++++++++ controllers/workspace/status.go | 28 +++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/controllers/workspace/devworkspace_controller.go b/controllers/workspace/devworkspace_controller.go index c452e6ef8..3497ca4ba 100644 --- a/controllers/workspace/devworkspace_controller.go +++ b/controllers/workspace/devworkspace_controller.go @@ -59,6 +59,10 @@ import ( dw "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2" ) +const ( + startingWorkspaceRequeueInterval = 5 * time.Second +) + // DevWorkspaceReconciler reconciles a DevWorkspace object type DevWorkspaceReconciler struct { client.Client @@ -181,8 +185,16 @@ func (r *DevWorkspaceReconciler) Reconcile(ctx context.Context, req ctrl.Request clusterWorkspace := workspace.DeepCopy() timingInfo := map[string]string{} timing.SetTime(timingInfo, timing.DevWorkspaceStarted) + defer func() (reconcile.Result, error) { r.syncTimingToCluster(ctx, clusterWorkspace, timingInfo, reqLogger) + // Don't accidentally suppress errors by overwriting here; only check for timeout when no error + // encountered in main reconcile loop. + if err == nil { + if timeoutErr := checkForStartTimeOut(clusterWorkspace, reqLogger, &reconcileStatus); timeoutErr != nil { + reconcileResult, err = r.failWorkspace(workspace, timeoutErr.Error(), reqLogger, &reconcileStatus) + } + } return r.updateWorkspaceStatus(clusterWorkspace, reqLogger, &reconcileStatus, reconcileResult, err) }() @@ -286,6 +298,9 @@ func (r *DevWorkspaceReconciler) Reconcile(ctx context.Context, req ctrl.Request message = routingStatus.Message } reconcileStatus.setConditionFalse(dw.DevWorkspaceRoutingReady, message) + if !routingStatus.Requeue && routingStatus.Err == nil { + return reconcile.Result{RequeueAfter: startingWorkspaceRequeueInterval}, nil + } return reconcile.Result{Requeue: routingStatus.Requeue}, routingStatus.Err } reconcileStatus.setConditionTrue(dw.DevWorkspaceRoutingReady, "Networking ready") @@ -333,6 +348,9 @@ func (r *DevWorkspaceReconciler) Reconcile(ctx context.Context, req ctrl.Request // FailStartup is not possible for generating the serviceaccount reqLogger.Info("Waiting for workspace ServiceAccount") reconcileStatus.setConditionFalse(dw.DevWorkspaceServiceAccountReady, "Waiting for DevWorkspace ServiceAccount") + if !serviceAcctStatus.Requeue && serviceAcctStatus.Err == nil { + return reconcile.Result{RequeueAfter: startingWorkspaceRequeueInterval}, nil + } return reconcile.Result{Requeue: serviceAcctStatus.Requeue}, serviceAcctStatus.Err } serviceAcctName := serviceAcctStatus.ServiceAccountName @@ -341,6 +359,9 @@ func (r *DevWorkspaceReconciler) Reconcile(ctx context.Context, req ctrl.Request pullSecretStatus := wsprovision.PullSecrets(clusterAPI, serviceAcctName, workspace.GetNamespace()) if !pullSecretStatus.Continue { reconcileStatus.setConditionFalse(conditions.PullSecretsReady, "Waiting for DevWorkspace pull secrets") + if !pullSecretStatus.Requeue && pullSecretStatus.Err == nil { + return reconcile.Result{RequeueAfter: startingWorkspaceRequeueInterval}, nil + } return reconcile.Result{Requeue: pullSecretStatus.Requeue}, pullSecretStatus.Err } allPodAdditions = append(allPodAdditions, pullSecretStatus.PodAdditions) @@ -355,6 +376,9 @@ func (r *DevWorkspaceReconciler) Reconcile(ctx context.Context, req ctrl.Request } reqLogger.Info("Waiting on deployment to be ready") reconcileStatus.setConditionFalse(conditions.DeploymentReady, "Waiting for workspace deployment") + if !deploymentStatus.Requeue && deploymentStatus.Err == nil { + return reconcile.Result{RequeueAfter: startingWorkspaceRequeueInterval}, nil + } return reconcile.Result{Requeue: deploymentStatus.Requeue}, deploymentStatus.Err } reconcileStatus.setConditionTrue(conditions.DeploymentReady, "DevWorkspace deployment ready") diff --git a/controllers/workspace/status.go b/controllers/workspace/status.go index 338eb261e..3d859963c 100644 --- a/controllers/workspace/status.go +++ b/controllers/workspace/status.go @@ -19,6 +19,7 @@ import ( "net/http" "net/url" "sort" + "time" dw "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2" @@ -31,6 +32,7 @@ import ( "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1" "github.com/devfile/devworkspace-operator/controllers/workspace/metrics" "github.com/devfile/devworkspace-operator/pkg/conditions" + "github.com/devfile/devworkspace-operator/pkg/config" wsprovision "github.com/devfile/devworkspace-operator/pkg/provision/workspace" ) @@ -238,3 +240,29 @@ func updateMetricsForPhase(workspace *dw.DevWorkspace, oldPhase, newPhase dw.Dev metrics.WorkspaceStarted(workspace, logger) } } + +// checkForStartTimeOut checks if the provided workspace has not progressed for longer than the configured +// startup timeout. This is determined by checking to see if the last condition transition time is more +// than [timeout] duration ago. Workspaces that are not in the "Starting" phase cannot timeout. Returns +// an error with message when timeout is reached. +func checkForStartTimeOut(workspace *dw.DevWorkspace, logger logr.Logger, status *currentStatus) error { + if workspace.Status.Phase != dw.DevWorkspaceStatusStarting { + return nil + } + timeout, err := time.ParseDuration(config.Workspace.StartProgressTimeout) + if err != nil { + return fmt.Errorf("invalid duration specified for timeout: %w", err) + } + currTime := clock.Now() + lastUpdateTime := time.Time{} + for _, condition := range workspace.Status.Conditions { + if condition.LastTransitionTime.Time.After(lastUpdateTime) { + lastUpdateTime = condition.LastTransitionTime.Time + } + } + if !lastUpdateTime.IsZero() && lastUpdateTime.Add(timeout).Before(currTime) { + return fmt.Errorf("devworkspace failed to progress past phase '%s' for longer than timeout (%s)", + workspace.Status.Phase, config.Workspace.StartProgressTimeout) + } + return nil +} From 947938018fec541a7b1609e449801cde15ef6bfa Mon Sep 17 00:00:00 2001 From: Angel Misevski Date: Mon, 27 Sep 2021 16:01:22 -0400 Subject: [PATCH 4/4] Rename startProgressTimeout to progressTimeout and use for Failing dws Rename startProgressTimeout to progressTimeout and repurpose it to detect workspaces stuck in the "Failing" state for too long as well. Signed-off-by: Angel Misevski --- .../devworkspaceoperatorconfig_types.go | 6 ++-- .../workspace/devworkspace_controller.go | 8 +++-- controllers/workspace/status.go | 33 ++++++++++++++++--- ...evfile.io_devworkspaceoperatorconfigs.yaml | 6 ++-- deploy/deployment/kubernetes/combined.yaml | 16 ++++----- ...r.devfile.io.CustomResourceDefinition.yaml | 16 ++++----- deploy/deployment/openshift/combined.yaml | 16 ++++----- ...r.devfile.io.CustomResourceDefinition.yaml | 16 ++++----- ...evfile.io_devworkspaceoperatorconfigs.yaml | 16 ++++----- pkg/config/defaults.go | 8 ++--- pkg/config/sync.go | 4 +-- 11 files changed, 87 insertions(+), 58 deletions(-) diff --git a/apis/controller/v1alpha1/devworkspaceoperatorconfig_types.go b/apis/controller/v1alpha1/devworkspaceoperatorconfig_types.go index 35a393e55..224eb1c8a 100644 --- a/apis/controller/v1alpha1/devworkspaceoperatorconfig_types.go +++ b/apis/controller/v1alpha1/devworkspaceoperatorconfig_types.go @@ -61,11 +61,11 @@ type WorkspaceConfig struct { // requires support in the workspace being started. If not specified, the default // value of "15m" is used. IdleTimeout string `json:"idleTimeout,omitempty"` - // StartProgressTimeout determines the maximum duration a DevWorkspace can be in - // a "Starting" phase without progressing before it is automatically failed. + // ProgressTimeout determines the maximum duration a DevWorkspace can be in + // a "Starting" or "Failing" phase without progressing before it is automatically failed. // Duration should be specified in a format parseable by Go's time package, e.g. // "15m", "20s", "1h30m", etc. If not specified, the default value of "5m" is used. - StartProgressTimeout string `json:"startProgressTimeout,omitempty"` + ProgressTimeout string `json:"progressTimeout,omitempty"` // IgnoredUnrecoverableEvents defines a list of Kubernetes event names that should // be ignored when deciding to fail a DevWorkspace startup. This option should be used // if a transient cluster issue is triggering false-positives (for example, if diff --git a/controllers/workspace/devworkspace_controller.go b/controllers/workspace/devworkspace_controller.go index 3497ca4ba..f8e6036fd 100644 --- a/controllers/workspace/devworkspace_controller.go +++ b/controllers/workspace/devworkspace_controller.go @@ -138,7 +138,11 @@ func (r *DevWorkspaceReconciler) Reconcile(ctx context.Context, req ctrl.Request // If debug annotation is present, leave the deployment in place to let users // view logs. if workspace.Annotations[constants.DevWorkspaceDebugStartAnnotation] == "true" { - return reconcile.Result{}, nil + if isTimeout, err := checkForFailingTimeout(workspace); err != nil { + return reconcile.Result{}, err + } else if !isTimeout { + return reconcile.Result{}, nil + } } patch := []byte(`{"spec":{"started": false}}`) @@ -191,7 +195,7 @@ func (r *DevWorkspaceReconciler) Reconcile(ctx context.Context, req ctrl.Request // Don't accidentally suppress errors by overwriting here; only check for timeout when no error // encountered in main reconcile loop. if err == nil { - if timeoutErr := checkForStartTimeOut(clusterWorkspace, reqLogger, &reconcileStatus); timeoutErr != nil { + if timeoutErr := checkForStartTimeout(clusterWorkspace); timeoutErr != nil { reconcileResult, err = r.failWorkspace(workspace, timeoutErr.Error(), reqLogger, &reconcileStatus) } } diff --git a/controllers/workspace/status.go b/controllers/workspace/status.go index 3d859963c..58c64c365 100644 --- a/controllers/workspace/status.go +++ b/controllers/workspace/status.go @@ -241,15 +241,15 @@ func updateMetricsForPhase(workspace *dw.DevWorkspace, oldPhase, newPhase dw.Dev } } -// checkForStartTimeOut checks if the provided workspace has not progressed for longer than the configured +// checkForStartTimeout checks if the provided workspace has not progressed for longer than the configured // startup timeout. This is determined by checking to see if the last condition transition time is more // than [timeout] duration ago. Workspaces that are not in the "Starting" phase cannot timeout. Returns // an error with message when timeout is reached. -func checkForStartTimeOut(workspace *dw.DevWorkspace, logger logr.Logger, status *currentStatus) error { +func checkForStartTimeout(workspace *dw.DevWorkspace) error { if workspace.Status.Phase != dw.DevWorkspaceStatusStarting { return nil } - timeout, err := time.ParseDuration(config.Workspace.StartProgressTimeout) + timeout, err := time.ParseDuration(config.Workspace.ProgressTimeout) if err != nil { return fmt.Errorf("invalid duration specified for timeout: %w", err) } @@ -262,7 +262,32 @@ func checkForStartTimeOut(workspace *dw.DevWorkspace, logger logr.Logger, status } if !lastUpdateTime.IsZero() && lastUpdateTime.Add(timeout).Before(currTime) { return fmt.Errorf("devworkspace failed to progress past phase '%s' for longer than timeout (%s)", - workspace.Status.Phase, config.Workspace.StartProgressTimeout) + workspace.Status.Phase, config.Workspace.ProgressTimeout) } return nil } + +// checkForFailingTimeout checks that the current workspace has not been in the "Failing" state for longer than the +// configured progress timeout. If the workspace is not in the Failing state or does not have a DevWorkspaceFailed +// condition set, returns false. Otherwise, returns true if the workspace has timed out. Returns an error if +// timeout is configured with an unparsable duration. +func checkForFailingTimeout(workspace *dw.DevWorkspace) (isTimedOut bool, err error) { + if workspace.Status.Phase != devworkspacePhaseFailing { + return false, nil + } + timeout, err := time.ParseDuration(config.Workspace.ProgressTimeout) + if err != nil { + return false, fmt.Errorf("invalid duration specified for timeout: %w", err) + } + currTime := clock.Now() + failedTime := time.Time{} + for _, condition := range workspace.Status.Conditions { + if condition.Type == dw.DevWorkspaceFailedStart { + failedTime = condition.LastTransitionTime.Time + } + } + if !failedTime.IsZero() && failedTime.Add(timeout).Before(currTime) { + return true, nil + } + return false, nil +} diff --git a/deploy/bundle/manifests/controller.devfile.io_devworkspaceoperatorconfigs.yaml b/deploy/bundle/manifests/controller.devfile.io_devworkspaceoperatorconfigs.yaml index 431988dd9..b1d2ba42d 100644 --- a/deploy/bundle/manifests/controller.devfile.io_devworkspaceoperatorconfigs.yaml +++ b/deploy/bundle/manifests/controller.devfile.io_devworkspaceoperatorconfigs.yaml @@ -61,14 +61,14 @@ spec: - Always - Never type: string + progressTimeout: + description: ProgressTimeout determines the maximum duration a DevWorkspace can be in a "Starting" or "Failing" phase without progressing before it is automatically failed. Duration should be specified in a format parseable by Go's time package, e.g. "15m", "20s", "1h30m", etc. If not specified, the default value of "5m" is used. + type: string pvcName: description: PVCName defines the name used for the persistent volume claim created to support workspace storage when the 'common' storage class is used. If not specified, the default value of `claim-devworkspace` is used. maxLength: 63 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string - startProgressTimeout: - description: StartProgressTimeout determines the maximum duration a DevWorkspace can be in a "Starting" phase without progressing before it is automatically failed. Duration should be specified in a format parseable by Go's time package, e.g. "15m", "20s", "1h30m", etc. If not specified, the default value of "5m" is used. - type: string storageClassName: description: StorageClassName defines and optional storageClass to use for persistent volume claims created to support DevWorkspaces type: string diff --git a/deploy/deployment/kubernetes/combined.yaml b/deploy/deployment/kubernetes/combined.yaml index 2e729346b..40cadb94e 100644 --- a/deploy/deployment/kubernetes/combined.yaml +++ b/deploy/deployment/kubernetes/combined.yaml @@ -87,6 +87,14 @@ spec: - Always - Never type: string + progressTimeout: + description: ProgressTimeout determines the maximum duration a + DevWorkspace can be in a "Starting" or "Failing" phase without + progressing before it is automatically failed. Duration should + be specified in a format parseable by Go's time package, e.g. + "15m", "20s", "1h30m", etc. If not specified, the default value + of "5m" is used. + type: string pvcName: description: PVCName defines the name used for the persistent volume claim created to support workspace storage when the 'common' @@ -95,14 +103,6 @@ spec: maxLength: 63 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string - startProgressTimeout: - description: StartProgressTimeout determines the maximum duration - a DevWorkspace can be in a "Starting" phase without progressing - before it is automatically failed. Duration should be specified - in a format parseable by Go's time package, e.g. "15m", "20s", - "1h30m", etc. If not specified, the default value of "5m" is - used. - type: string storageClassName: description: StorageClassName defines and optional storageClass to use for persistent volume claims created to support DevWorkspaces 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 8c633f434..4a2d0d493 100644 --- a/deploy/deployment/kubernetes/objects/devworkspaceoperatorconfigs.controller.devfile.io.CustomResourceDefinition.yaml +++ b/deploy/deployment/kubernetes/objects/devworkspaceoperatorconfigs.controller.devfile.io.CustomResourceDefinition.yaml @@ -87,6 +87,14 @@ spec: - Always - Never type: string + progressTimeout: + description: ProgressTimeout determines the maximum duration a + DevWorkspace can be in a "Starting" or "Failing" phase without + progressing before it is automatically failed. Duration should + be specified in a format parseable by Go's time package, e.g. + "15m", "20s", "1h30m", etc. If not specified, the default value + of "5m" is used. + type: string pvcName: description: PVCName defines the name used for the persistent volume claim created to support workspace storage when the 'common' @@ -95,14 +103,6 @@ spec: maxLength: 63 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string - startProgressTimeout: - description: StartProgressTimeout determines the maximum duration - a DevWorkspace can be in a "Starting" phase without progressing - before it is automatically failed. Duration should be specified - in a format parseable by Go's time package, e.g. "15m", "20s", - "1h30m", etc. If not specified, the default value of "5m" is - used. - type: string storageClassName: description: StorageClassName defines and optional storageClass to use for persistent volume claims created to support DevWorkspaces diff --git a/deploy/deployment/openshift/combined.yaml b/deploy/deployment/openshift/combined.yaml index 670f262a5..1f6cbb4ab 100644 --- a/deploy/deployment/openshift/combined.yaml +++ b/deploy/deployment/openshift/combined.yaml @@ -87,6 +87,14 @@ spec: - Always - Never type: string + progressTimeout: + description: ProgressTimeout determines the maximum duration a + DevWorkspace can be in a "Starting" or "Failing" phase without + progressing before it is automatically failed. Duration should + be specified in a format parseable by Go's time package, e.g. + "15m", "20s", "1h30m", etc. If not specified, the default value + of "5m" is used. + type: string pvcName: description: PVCName defines the name used for the persistent volume claim created to support workspace storage when the 'common' @@ -95,14 +103,6 @@ spec: maxLength: 63 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string - startProgressTimeout: - description: StartProgressTimeout determines the maximum duration - a DevWorkspace can be in a "Starting" phase without progressing - before it is automatically failed. Duration should be specified - in a format parseable by Go's time package, e.g. "15m", "20s", - "1h30m", etc. If not specified, the default value of "5m" is - used. - type: string storageClassName: description: StorageClassName defines and optional storageClass to use for persistent volume claims created to support DevWorkspaces 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 8c633f434..4a2d0d493 100644 --- a/deploy/deployment/openshift/objects/devworkspaceoperatorconfigs.controller.devfile.io.CustomResourceDefinition.yaml +++ b/deploy/deployment/openshift/objects/devworkspaceoperatorconfigs.controller.devfile.io.CustomResourceDefinition.yaml @@ -87,6 +87,14 @@ spec: - Always - Never type: string + progressTimeout: + description: ProgressTimeout determines the maximum duration a + DevWorkspace can be in a "Starting" or "Failing" phase without + progressing before it is automatically failed. Duration should + be specified in a format parseable by Go's time package, e.g. + "15m", "20s", "1h30m", etc. If not specified, the default value + of "5m" is used. + type: string pvcName: description: PVCName defines the name used for the persistent volume claim created to support workspace storage when the 'common' @@ -95,14 +103,6 @@ spec: maxLength: 63 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string - startProgressTimeout: - description: StartProgressTimeout determines the maximum duration - a DevWorkspace can be in a "Starting" phase without progressing - before it is automatically failed. Duration should be specified - in a format parseable by Go's time package, e.g. "15m", "20s", - "1h30m", etc. If not specified, the default value of "5m" is - used. - type: string storageClassName: description: StorageClassName defines and optional storageClass to use for persistent volume claims created to support DevWorkspaces diff --git a/deploy/templates/crd/bases/controller.devfile.io_devworkspaceoperatorconfigs.yaml b/deploy/templates/crd/bases/controller.devfile.io_devworkspaceoperatorconfigs.yaml index e0c3a4353..696cb60b9 100644 --- a/deploy/templates/crd/bases/controller.devfile.io_devworkspaceoperatorconfigs.yaml +++ b/deploy/templates/crd/bases/controller.devfile.io_devworkspaceoperatorconfigs.yaml @@ -86,6 +86,14 @@ spec: - Always - Never type: string + progressTimeout: + description: ProgressTimeout determines the maximum duration a + DevWorkspace can be in a "Starting" or "Failing" phase without + progressing before it is automatically failed. Duration should + be specified in a format parseable by Go's time package, e.g. + "15m", "20s", "1h30m", etc. If not specified, the default value + of "5m" is used. + type: string pvcName: description: PVCName defines the name used for the persistent volume claim created to support workspace storage when the 'common' @@ -94,14 +102,6 @@ spec: maxLength: 63 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string - startProgressTimeout: - description: StartProgressTimeout determines the maximum duration - a DevWorkspace can be in a "Starting" phase without progressing - before it is automatically failed. Duration should be specified - in a format parseable by Go's time package, e.g. "15m", "20s", - "1h30m", etc. If not specified, the default value of "5m" is - used. - type: string storageClassName: description: StorageClassName defines and optional storageClass to use for persistent volume claims created to support DevWorkspaces diff --git a/pkg/config/defaults.go b/pkg/config/defaults.go index 245146415..e10f06367 100644 --- a/pkg/config/defaults.go +++ b/pkg/config/defaults.go @@ -21,9 +21,9 @@ var DefaultConfig = &v1alpha1.OperatorConfiguration{ ClusterHostSuffix: "", // is auto discovered when running on OpenShift. Must be defined by CR on Kubernetes. }, Workspace: &v1alpha1.WorkspaceConfig{ - ImagePullPolicy: "Always", - PVCName: "claim-devworkspace", - IdleTimeout: "15m", - StartProgressTimeout: "5m", + ImagePullPolicy: "Always", + PVCName: "claim-devworkspace", + IdleTimeout: "15m", + ProgressTimeout: "5m", }, } diff --git a/pkg/config/sync.go b/pkg/config/sync.go index 6bda7553e..77aabc1a4 100644 --- a/pkg/config/sync.go +++ b/pkg/config/sync.go @@ -205,8 +205,8 @@ func mergeConfig(from, to *controller.OperatorConfiguration) { if from.Workspace.IdleTimeout != "" { to.Workspace.IdleTimeout = from.Workspace.IdleTimeout } - if from.Workspace.StartProgressTimeout != "" { - to.Workspace.StartProgressTimeout = from.Workspace.StartProgressTimeout + if from.Workspace.ProgressTimeout != "" { + to.Workspace.ProgressTimeout = from.Workspace.ProgressTimeout } if from.Workspace.IgnoredUnrecoverableEvents != nil { to.Workspace.IgnoredUnrecoverableEvents = from.Workspace.IgnoredUnrecoverableEvents