mirror of https://github.com/openkruise/kruise.git
fix cloneset webhooke check podstodelete
This commit is contained in:
parent
b1f24ee0e0
commit
de531d620e
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue