From 7bb68bc4346600f0939f272abcbb080c658ea4ab Mon Sep 17 00:00:00 2001 From: Michail Kargakis Date: Thu, 15 Sep 2016 17:55:25 +0200 Subject: [PATCH] extensions: api changes for perma-failed deployments --- pkg/apis/extensions/types.go | 46 ++++++++++++++++++++ pkg/apis/extensions/v1beta1/conversion.go | 8 ++++ pkg/apis/extensions/v1beta1/defaults_test.go | 6 ++- pkg/apis/extensions/v1beta1/types.go | 46 ++++++++++++++++++++ pkg/apis/extensions/validation/validation.go | 3 ++ 5 files changed, 107 insertions(+), 2 deletions(-) diff --git a/pkg/apis/extensions/types.go b/pkg/apis/extensions/types.go index 7d7cd8a8d1b..f80ac23c45f 100644 --- a/pkg/apis/extensions/types.go +++ b/pkg/apis/extensions/types.go @@ -208,9 +208,19 @@ type DeploymentSpec struct { // deployment controller. // +optional Paused bool `json:"paused,omitempty"` + // The config this deployment is rolling back to. Will be cleared after rollback is done. // +optional RollbackTo *RollbackConfig `json:"rollbackTo,omitempty"` + + // The maximum time in seconds for a deployment to make progress before it + // is considered to be failed. The deployment controller will continue to + // process failed deployments and a condition with a ProgressDeadlineExceeded + // reason will be surfaced in the deployment status. Once autoRollback is + // implemented, the deployment controller will automatically rollback failed + // deployments. Note that progress will not be estimated during the time a + // deployment is paused. This is not set by default. + ProgressDeadlineSeconds *int32 `json:"progressDeadlineSeconds,omitempty"` } // DeploymentRollback stores the information required to rollback a deployment. @@ -311,6 +321,42 @@ type DeploymentStatus struct { // Total number of unavailable pods targeted by this deployment. // +optional UnavailableReplicas int32 `json:"unavailableReplicas,omitempty"` + + // Represents the latest available observations of a deployment's current state. + Conditions []DeploymentCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` +} + +type DeploymentConditionType string + +// These are valid conditions of a deployment. +const ( + // Available means the deployment is available, ie. at least the minimum available + // replicas required are up and running for at least minReadySeconds. + DeploymentAvailable DeploymentConditionType = "Available" + // Progressing means the deployment is progressing. Progress for a deployment is + // considered when a new replica set is created or adopted, and when new pods scale + // up or old pods scale down. Progress is not estimated for paused deployments or + // when progressDeadlineSeconds is not specified. + DeploymentProgressing DeploymentConditionType = "Progressing" + // ReplicaFailure is added in a deployment when one of its pods fails to be created + // or deleted. + DeploymentReplicaFailure DeploymentConditionType = "ReplicaFailure" +) + +// DeploymentCondition describes the state of a deployment at a certain point. +type DeploymentCondition struct { + // Type of deployment condition. + Type DeploymentConditionType `json:"type"` + // Status of the condition, one of True, False, Unknown. + Status api.ConditionStatus `json:"status"` + // The last time this condition was updated. + LastUpdateTime unversioned.Time `json:"lastUpdateTime,omitempty"` + // Last time the condition transitioned from one status to another. + LastTransitionTime unversioned.Time `json:"lastTransitionTime,omitempty"` + // The reason for the condition's last transition. + Reason string `json:"reason,omitempty"` + // A human readable message indicating details about the transition. + Message string `json:"message,omitempty"` } type DeploymentList struct { diff --git a/pkg/apis/extensions/v1beta1/conversion.go b/pkg/apis/extensions/v1beta1/conversion.go index 5501f40369d..0c1c37d0477 100644 --- a/pkg/apis/extensions/v1beta1/conversion.go +++ b/pkg/apis/extensions/v1beta1/conversion.go @@ -153,6 +153,10 @@ func Convert_extensions_DeploymentSpec_To_v1beta1_DeploymentSpec(in *extensions. } else { out.RollbackTo = nil } + if in.ProgressDeadlineSeconds != nil { + out.ProgressDeadlineSeconds = new(int32) + *out.ProgressDeadlineSeconds = *in.ProgressDeadlineSeconds + } return nil } @@ -176,6 +180,10 @@ func Convert_v1beta1_DeploymentSpec_To_extensions_DeploymentSpec(in *DeploymentS } else { out.RollbackTo = nil } + if in.ProgressDeadlineSeconds != nil { + out.ProgressDeadlineSeconds = new(int32) + *out.ProgressDeadlineSeconds = *in.ProgressDeadlineSeconds + } return nil } diff --git a/pkg/apis/extensions/v1beta1/defaults_test.go b/pkg/apis/extensions/v1beta1/defaults_test.go index e6741f1efbf..add8ce0850d 100644 --- a/pkg/apis/extensions/v1beta1/defaults_test.go +++ b/pkg/apis/extensions/v1beta1/defaults_test.go @@ -252,6 +252,7 @@ func TestSetDefaultDeployment(t *testing.T) { Strategy: DeploymentStrategy{ Type: RecreateDeploymentStrategyType, }, + ProgressDeadlineSeconds: newInt32(30), }, }, expected: &Deployment{ @@ -260,7 +261,8 @@ func TestSetDefaultDeployment(t *testing.T) { Strategy: DeploymentStrategy{ Type: RecreateDeploymentStrategyType, }, - Template: defaultTemplate, + Template: defaultTemplate, + ProgressDeadlineSeconds: newInt32(30), }, }, }, @@ -276,7 +278,7 @@ func TestSetDefaultDeployment(t *testing.T) { t.FailNow() } if !reflect.DeepEqual(got.Spec, expected.Spec) { - t.Errorf("got different than expected:\n\t%+v\ngot:\n\t%+v", got.Spec, expected.Spec) + t.Errorf("object mismatch!\nexpected:\n\t%+v\ngot:\n\t%+v", got.Spec, expected.Spec) } } } diff --git a/pkg/apis/extensions/v1beta1/types.go b/pkg/apis/extensions/v1beta1/types.go index 8abef073253..e0ab8a9898c 100644 --- a/pkg/apis/extensions/v1beta1/types.go +++ b/pkg/apis/extensions/v1beta1/types.go @@ -288,9 +288,19 @@ type DeploymentSpec struct { // deployment controller. // +optional Paused bool `json:"paused,omitempty" protobuf:"varint,7,opt,name=paused"` + // The config this deployment is rolling back to. Will be cleared after rollback is done. // +optional RollbackTo *RollbackConfig `json:"rollbackTo,omitempty" protobuf:"bytes,8,opt,name=rollbackTo"` + + // The maximum time in seconds for a deployment to make progress before it + // is considered to be failed. The deployment controller will continue to + // process failed deployments and a condition with a ProgressDeadlineExceeded + // reason will be surfaced in the deployment status. Once autoRollback is + // implemented, the deployment controller will automatically rollback failed + // deployments. Note that progress will not be estimated during the time a + // deployment is paused. This is not set by default. + ProgressDeadlineSeconds *int32 `json:"progressDeadlineSeconds,omitempty"` } // DeploymentRollback stores the information required to rollback a deployment. @@ -394,6 +404,42 @@ type DeploymentStatus struct { // Total number of unavailable pods targeted by this deployment. // +optional UnavailableReplicas int32 `json:"unavailableReplicas,omitempty" protobuf:"varint,5,opt,name=unavailableReplicas"` + + // Represents the latest available observations of a deployment's current state. + Conditions []DeploymentCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` +} + +type DeploymentConditionType string + +// These are valid conditions of a deployment. +const ( + // Available means the deployment is available, ie. at least the minimum available + // replicas required are up and running for at least minReadySeconds. + DeploymentAvailable DeploymentConditionType = "Available" + // Progressing means the deployment is progressing. Progress for a deployment is + // considered when a new replica set is created or adopted, and when new pods scale + // up or old pods scale down. Progress is not estimated for paused deployments or + // when progressDeadlineSeconds is not specified. + DeploymentProgressing DeploymentConditionType = "Progressing" + // ReplicaFailure is added in a deployment when one of its pods fails to be created + // or deleted. + DeploymentReplicaFailure DeploymentConditionType = "ReplicaFailure" +) + +// DeploymentCondition describes the state of a deployment at a certain point. +type DeploymentCondition struct { + // Type of deployment condition. + Type DeploymentConditionType `json:"type" protobuf:"bytes,1,opt,name=type,casttype=DeploymentConditionType"` + // Status of the condition, one of True, False, Unknown. + Status v1.ConditionStatus `json:"status" protobuf:"bytes,2,opt,name=status,casttype=k8s.io/kubernetes/pkg/api/v1.ConditionStatus"` + // The last time this condition was updated. + LastUpdateTime unversioned.Time `json:"lastUpdateTime,omitempty"` + // Last time the condition transitioned from one status to another. + LastTransitionTime unversioned.Time `json:"lastTransitionTime,omitempty"` + // The reason for the condition's last transition. + Reason string `json:"reason,omitempty" protobuf:"bytes,4,opt,name=reason"` + // A human readable message indicating details about the transition. + Message string `json:"message,omitempty" protobuf:"bytes,5,opt,name=message"` } // DeploymentList is a list of Deployments. diff --git a/pkg/apis/extensions/validation/validation.go b/pkg/apis/extensions/validation/validation.go index 15d1e215616..02fc9795666 100644 --- a/pkg/apis/extensions/validation/validation.go +++ b/pkg/apis/extensions/validation/validation.go @@ -262,6 +262,9 @@ func ValidateDeploymentSpec(spec *extensions.DeploymentSpec, fldPath *field.Path if spec.RollbackTo != nil { allErrs = append(allErrs, ValidateRollback(spec.RollbackTo, fldPath.Child("rollback"))...) } + if spec.ProgressDeadlineSeconds != nil { + allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.ProgressDeadlineSeconds), fldPath.Child("progressDeadlineSeconds"))...) + } return allErrs }