mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Add collisionCount api field in DeploymentStatus
Signed-off-by: Michail Kargakis <mkargaki@redhat.com>
This commit is contained in:
parent
4def5add11
commit
4aa8b1a66a
@ -356,6 +356,12 @@ type DeploymentStatus struct {
|
||||
// +patchMergeKey=type
|
||||
// +patchStrategy=merge
|
||||
Conditions []DeploymentCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,6,rep,name=conditions"`
|
||||
|
||||
// Count of hash collisions for the Deployment. The Deployment controller uses this
|
||||
// field as a collision avoidance mechanism when it needs to create the name for the
|
||||
// newest ReplicaSet.
|
||||
// +optional
|
||||
CollisionCount *int64 `json:"collisionCount,omitempty"`
|
||||
}
|
||||
|
||||
type DeploymentConditionType string
|
||||
|
@ -327,6 +327,12 @@ type DeploymentStatus struct {
|
||||
|
||||
// Represents the latest available observations of a deployment's current state.
|
||||
Conditions []DeploymentCondition
|
||||
|
||||
// Count of hash collisions for the Deployment. The Deployment controller uses this
|
||||
// field as a collision avoidance mechanism when it needs to create the name for the
|
||||
// newest ReplicaSet.
|
||||
// +optional
|
||||
CollisionCount *int64
|
||||
}
|
||||
|
||||
type DeploymentConditionType string
|
||||
|
@ -325,6 +325,12 @@ type DeploymentStatus struct {
|
||||
// +patchMergeKey=type
|
||||
// +patchStrategy=merge
|
||||
Conditions []DeploymentCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,6,rep,name=conditions"`
|
||||
|
||||
// Count of hash collisions for the Deployment. The Deployment controller uses this
|
||||
// field as a collision avoidance mechanism when it needs to create the name for the
|
||||
// newest ReplicaSet.
|
||||
// +optional
|
||||
CollisionCount *int64 `json:"collisionCount,omitempty"`
|
||||
}
|
||||
|
||||
type DeploymentConditionType string
|
||||
|
@ -346,6 +346,9 @@ func ValidateDeploymentStatus(status *extensions.DeploymentStatus, fldPath *fiel
|
||||
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.ReadyReplicas), fldPath.Child("readyReplicas"))...)
|
||||
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.AvailableReplicas), fldPath.Child("availableReplicas"))...)
|
||||
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.UnavailableReplicas), fldPath.Child("unavailableReplicas"))...)
|
||||
if status.CollisionCount != nil {
|
||||
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(*status.CollisionCount, fldPath.Child("collisionCount"))...)
|
||||
}
|
||||
msg := "cannot be greater than status.replicas"
|
||||
if status.UpdatedReplicas > status.Replicas {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("updatedReplicas"), status.UpdatedReplicas, msg))
|
||||
@ -372,10 +375,29 @@ func ValidateDeploymentUpdate(update, old *extensions.Deployment) field.ErrorLis
|
||||
|
||||
func ValidateDeploymentStatusUpdate(update, old *extensions.Deployment) field.ErrorList {
|
||||
allErrs := apivalidation.ValidateObjectMetaUpdate(&update.ObjectMeta, &old.ObjectMeta, field.NewPath("metadata"))
|
||||
allErrs = append(allErrs, ValidateDeploymentStatus(&update.Status, field.NewPath("status"))...)
|
||||
fldPath := field.NewPath("status")
|
||||
allErrs = append(allErrs, ValidateDeploymentStatus(&update.Status, fldPath)...)
|
||||
if isDecremented(update.Status.CollisionCount, old.Status.CollisionCount) {
|
||||
value := int64(0)
|
||||
if update.Status.CollisionCount != nil {
|
||||
value = *update.Status.CollisionCount
|
||||
}
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("collisionCount"), value, "cannot be decremented"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// TODO: Move in "k8s.io/kubernetes/pkg/api/validation"
|
||||
func isDecremented(update, old *int64) bool {
|
||||
if update == nil && old != nil {
|
||||
return true
|
||||
}
|
||||
if update == nil || old == nil {
|
||||
return false
|
||||
}
|
||||
return *update < *old
|
||||
}
|
||||
|
||||
func ValidateDeployment(obj *extensions.Deployment) field.ErrorList {
|
||||
allErrs := apivalidation.ValidateObjectMeta(&obj.ObjectMeta, true, ValidateDeploymentName, field.NewPath("metadata"))
|
||||
allErrs = append(allErrs, ValidateDeploymentSpec(&obj.Spec, field.NewPath("spec"))...)
|
||||
|
@ -21,6 +21,8 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
@ -1230,6 +1232,11 @@ func TestValidateDeployment(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func int64p(i int) *int64 {
|
||||
i64 := int64(i)
|
||||
return &i64
|
||||
}
|
||||
|
||||
func TestValidateDeploymentStatus(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
@ -1239,6 +1246,7 @@ func TestValidateDeploymentStatus(t *testing.T) {
|
||||
readyReplicas int32
|
||||
availableReplicas int32
|
||||
observedGeneration int64
|
||||
collisionCount *int64
|
||||
|
||||
expectedErr bool
|
||||
}{
|
||||
@ -1335,6 +1343,13 @@ func TestValidateDeploymentStatus(t *testing.T) {
|
||||
observedGeneration: 1,
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "invalid collisionCount",
|
||||
replicas: 3,
|
||||
observedGeneration: 1,
|
||||
collisionCount: int64p(-3),
|
||||
expectedErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
@ -1344,10 +1359,82 @@ func TestValidateDeploymentStatus(t *testing.T) {
|
||||
ReadyReplicas: test.readyReplicas,
|
||||
AvailableReplicas: test.availableReplicas,
|
||||
ObservedGeneration: test.observedGeneration,
|
||||
CollisionCount: test.collisionCount,
|
||||
}
|
||||
|
||||
if hasErr := len(ValidateDeploymentStatus(&status, field.NewPath("status"))) > 0; hasErr != test.expectedErr {
|
||||
t.Errorf("%s: expected error: %t, got error: %t", test.name, test.expectedErr, hasErr)
|
||||
errs := ValidateDeploymentStatus(&status, field.NewPath("status"))
|
||||
if hasErr := len(errs) > 0; hasErr != test.expectedErr {
|
||||
errString := spew.Sprintf("%#v", errs)
|
||||
t.Errorf("%s: expected error: %t, got error: %t\nerrors: %s", test.name, test.expectedErr, hasErr, errString)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateDeploymentStatusUpdate(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
from, to extensions.DeploymentStatus
|
||||
|
||||
expectedErr bool
|
||||
}{
|
||||
{
|
||||
name: "increase: valid update",
|
||||
from: extensions.DeploymentStatus{
|
||||
CollisionCount: nil,
|
||||
},
|
||||
to: extensions.DeploymentStatus{
|
||||
CollisionCount: int64p(1),
|
||||
},
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "stable: valid update",
|
||||
from: extensions.DeploymentStatus{
|
||||
CollisionCount: int64p(1),
|
||||
},
|
||||
to: extensions.DeploymentStatus{
|
||||
CollisionCount: int64p(1),
|
||||
},
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "unset: invalid update",
|
||||
from: extensions.DeploymentStatus{
|
||||
CollisionCount: int64p(1),
|
||||
},
|
||||
to: extensions.DeploymentStatus{
|
||||
CollisionCount: nil,
|
||||
},
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "decrease: invalid update",
|
||||
from: extensions.DeploymentStatus{
|
||||
CollisionCount: int64p(2),
|
||||
},
|
||||
to: extensions.DeploymentStatus{
|
||||
CollisionCount: int64p(1),
|
||||
},
|
||||
expectedErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
meta := metav1.ObjectMeta{Name: "foo", Namespace: metav1.NamespaceDefault, ResourceVersion: "1"}
|
||||
from := &extensions.Deployment{
|
||||
ObjectMeta: meta,
|
||||
Status: test.from,
|
||||
}
|
||||
to := &extensions.Deployment{
|
||||
ObjectMeta: meta,
|
||||
Status: test.to,
|
||||
}
|
||||
|
||||
errs := ValidateDeploymentStatusUpdate(to, from)
|
||||
if hasErr := len(errs) > 0; hasErr != test.expectedErr {
|
||||
errString := spew.Sprintf("%#v", errs)
|
||||
t.Errorf("%s: expected error: %t, got error: %t\nerrors: %s", test.name, test.expectedErr, hasErr, errString)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user