fix cloneset webhooke check podstodelete

This commit is contained in:
JunjunLi 2020-12-02 10:31:59 +08:00 committed by Siyu Wang
parent b1f24ee0e0
commit de531d620e
3 changed files with 74 additions and 10 deletions

View File

@ -48,7 +48,7 @@ func (h *CloneSetCreateUpdateHandler) Handle(ctx context.Context, req admission.
switch req.AdmissionRequest.Operation {
case admissionv1beta1.Create:
if allErrs := h.validateCloneSet(obj); len(allErrs) > 0 {
if allErrs := h.validateCloneSet(obj, nil); len(allErrs) > 0 {
return admission.Errored(http.StatusUnprocessableEntity, allErrs.ToAggregate())
}
case admissionv1beta1.Update:

View File

@ -15,18 +15,23 @@ import (
unversionedvalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
"k8s.io/apimachinery/pkg/types"
intstrutil "k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation/field"
appsvalidation "k8s.io/kubernetes/pkg/apis/apps/validation"
apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
)
func (h *CloneSetCreateUpdateHandler) validateCloneSet(cloneSet *appsv1alpha1.CloneSet) field.ErrorList {
func (h *CloneSetCreateUpdateHandler) validateCloneSet(cloneSet, oldCloneSet *appsv1alpha1.CloneSet) field.ErrorList {
allErrs := apivalidation.ValidateObjectMeta(&cloneSet.ObjectMeta, true, apimachineryvalidation.NameIsDNSSubdomain, field.NewPath("metadata"))
allErrs = append(allErrs, h.validateCloneSetSpec(&cloneSet.Spec, &cloneSet.ObjectMeta, field.NewPath("spec"))...)
var oldCloneSetSpec *appsv1alpha1.CloneSetSpec
if oldCloneSet != nil {
oldCloneSetSpec = &oldCloneSet.Spec
}
allErrs = append(allErrs, h.validateCloneSetSpec(&cloneSet.Spec, oldCloneSetSpec, &cloneSet.ObjectMeta, field.NewPath("spec"))...)
return allErrs
}
func (h *CloneSetCreateUpdateHandler) validateCloneSetSpec(spec *appsv1alpha1.CloneSetSpec, metadata *metav1.ObjectMeta, fldPath *field.Path) field.ErrorList {
func (h *CloneSetCreateUpdateHandler) validateCloneSetSpec(spec, oldSpec *appsv1alpha1.CloneSetSpec, metadata *metav1.ObjectMeta, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.Replicas), fldPath.Child("replicas"))...)
@ -58,13 +63,18 @@ func (h *CloneSetCreateUpdateHandler) validateCloneSetSpec(spec *appsv1alpha1.Cl
allErrs = append(allErrs, field.Forbidden(fldPath.Child("template", "spec", "activeDeadlineSeconds"), "activeDeadlineSeconds in cloneset is not Supported"))
}
allErrs = append(allErrs, h.validateScaleStrategy(&spec.ScaleStrategy, metadata, fldPath.Child("scaleStrategy"))...)
var oldScaleStrategy *appsv1alpha1.CloneSetScaleStrategy
if oldSpec != nil {
oldScaleStrategy = &oldSpec.ScaleStrategy
}
allErrs = append(allErrs, h.validateScaleStrategy(&spec.ScaleStrategy, oldScaleStrategy, metadata, fldPath.Child("scaleStrategy"))...)
allErrs = append(allErrs, h.validateUpdateStrategy(&spec.UpdateStrategy, int(*spec.Replicas), fldPath.Child("updateStrategy"))...)
return allErrs
}
func (h *CloneSetCreateUpdateHandler) validateScaleStrategy(strategy *appsv1alpha1.CloneSetScaleStrategy, metadata *metav1.ObjectMeta, fldPath *field.Path) field.ErrorList {
func (h *CloneSetCreateUpdateHandler) validateScaleStrategy(strategy, oldStrategy *appsv1alpha1.CloneSetScaleStrategy, metadata *metav1.ObjectMeta, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if list := util.CheckDuplicate(strategy.PodsToDelete); len(list) > 0 {
@ -72,7 +82,13 @@ func (h *CloneSetCreateUpdateHandler) validateScaleStrategy(strategy *appsv1alph
return allErrs
}
for _, podName := range strategy.PodsToDelete {
podsToDeleteSet := sets.NewString(strategy.PodsToDelete...)
if oldStrategy != nil && len(oldStrategy.PodsToDelete) > 0 {
podsToDeleteSet.Delete(oldStrategy.PodsToDelete...)
}
for _, podName := range podsToDeleteSet.List() {
pod := &v1.Pod{}
if err := h.Client.Get(context.TODO(), types.NamespacedName{Namespace: metadata.Namespace, Name: podName}, pod); err != nil {
allErrs = append(allErrs, field.Invalid(fldPath.Child("podsToDelete"), podName, fmt.Sprintf("find pod %s failed: %v", podName, err)))
@ -166,6 +182,6 @@ func (h *CloneSetCreateUpdateHandler) validateCloneSetUpdate(cloneSet, oldCloneS
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec"), err.Error()))
}
allErrs = append(allErrs, h.validateCloneSet(cloneSet)...)
allErrs = append(allErrs, h.validateCloneSet(cloneSet, oldCloneSet)...)
return allErrs
}

View File

@ -185,6 +185,38 @@ func TestValidate(t *testing.T) {
PodsToDelete: []string{"p1"},
},
UpdateStrategy: appsv1alpha1.CloneSetUpdateStrategy{
Type: appsv1alpha1.RecreateCloneSetUpdateStrategyType,
Partition: util.GetIntOrStrPointer(intstr.FromInt(2)),
MaxUnavailable: &intOrStr1,
},
},
},
{
// test oldSpec not-exits spec exits case
spec: &appsv1alpha1.CloneSetSpec{
Replicas: &val1,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate.Template,
RevisionHistoryLimit: &val1,
ScaleStrategy: appsv1alpha1.CloneSetScaleStrategy{
PodsToDelete: []string{"p0"},
},
UpdateStrategy: appsv1alpha1.CloneSetUpdateStrategy{
Type: appsv1alpha1.InPlaceOnlyCloneSetUpdateStrategyType,
Partition: util.GetIntOrStrPointer(intstr.FromInt(2)),
MaxUnavailable: &intOrStr1,
},
},
oldSpec: &appsv1alpha1.CloneSetSpec{
Replicas: &val2,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate1.Template,
RevisionHistoryLimit: &val2,
ScaleStrategy: appsv1alpha1.CloneSetScaleStrategy{
PodsToDelete: []string{},
},
UpdateStrategy: appsv1alpha1.CloneSetUpdateStrategy{
Type: appsv1alpha1.RecreateCloneSetUpdateStrategyType,
Partition: util.GetIntOrStrPointer(intstr.FromInt(2)),
@ -202,7 +234,7 @@ func TestValidate(t *testing.T) {
}
h := CloneSetCreateUpdateHandler{Client: fake.NewFakeClient(&p0)}
if successCase.oldSpec == nil {
if errs := h.validateCloneSet(&obj); len(errs) != 0 {
if errs := h.validateCloneSet(&obj, nil); len(errs) != 0 {
t.Errorf("expected success: %v", errs)
}
} else {
@ -333,6 +365,22 @@ func TestValidate(t *testing.T) {
},
},
},
// test pod-to-delete not-exits case
"invalid-podsToDelete-3": {
spec: &appsv1alpha1.CloneSetSpec{
Replicas: &val1,
Selector: &metav1.LabelSelector{MatchLabels: validLabels},
Template: validPodTemplate.Template,
UpdateStrategy: appsv1alpha1.CloneSetUpdateStrategy{
Type: appsv1alpha1.InPlaceIfPossibleCloneSetUpdateStrategyType,
Partition: util.GetIntOrStrPointer(intstr.FromInt(2)),
MaxUnavailable: &intOrStr1,
},
ScaleStrategy: appsv1alpha1.CloneSetScaleStrategy{
PodsToDelete: []string{"p1"},
},
},
},
"invalid-cloneset-update-1": {
spec: &appsv1alpha1.CloneSetSpec{
Replicas: &val1,
@ -365,7 +413,7 @@ func TestValidate(t *testing.T) {
}
h := CloneSetCreateUpdateHandler{Client: fake.NewFakeClient(&p0)}
if v.oldSpec == nil {
if errs := h.validateCloneSet(&obj); len(errs) == 0 {
if errs := h.validateCloneSet(&obj, nil); len(errs) == 0 {
t.Errorf("expected failure for %v", k)
}
} else {