webhook validate v1beta1 rollout
Signed-off-by: liheng.zms <liheng.zms@alibaba-inc.com>
This commit is contained in:
parent
9dcf3659d2
commit
3475d30470
|
|
@ -152,6 +152,7 @@ webhooks:
|
|||
- rollouts.kruise.io
|
||||
apiVersions:
|
||||
- v1alpha1
|
||||
- v1beta1
|
||||
operations:
|
||||
- CREATE
|
||||
- UPDATE
|
||||
|
|
|
|||
|
|
@ -62,6 +62,11 @@ func (m *canaryReleaseManager) runCanary(c *RolloutContext) error {
|
|||
// update podTemplateHash, Why is this position assigned?
|
||||
// Because If workload is deployment, only after canary pod already was created,
|
||||
// we can get the podTemplateHash from pod.annotations[pod-template-hash]
|
||||
// PodTemplateHash is used to select a new version of the Pod.
|
||||
|
||||
// Note:
|
||||
// In a scenario of successive releases v1->v2->v3, It is possible that this is the PodTemplateHash value of v2,
|
||||
// so it needs to be set later in the stepUpgrade
|
||||
if canaryStatus.PodTemplateHash == "" {
|
||||
canaryStatus.PodTemplateHash = c.Workload.PodTemplateHash
|
||||
}
|
||||
|
|
@ -185,6 +190,8 @@ func (m *canaryReleaseManager) doCanaryUpgrade(c *RolloutContext) (bool, error)
|
|||
m.recorder.Eventf(c.Rollout, corev1.EventTypeNormal, "Progressing", fmt.Sprintf("upgrade step(%d) canary pods with new versions done", canaryStatus.CurrentStepIndex))
|
||||
klog.Infof("rollout(%s/%s) batch(%s) state(%s), and success",
|
||||
c.Rollout.Namespace, c.Rollout.Name, util.DumpJSON(br.Status), br.Status.CanaryStatus.CurrentBatchState)
|
||||
// set the latest PodTemplateHash to selector the latest pods.
|
||||
canaryStatus.PodTemplateHash = c.Workload.PodTemplateHash
|
||||
return true, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -181,23 +181,10 @@ func (h *RolloutCreateUpdateHandler) validateRolloutConflict(rollout *appsv1beta
|
|||
|
||||
func validateRolloutSpec(rollout *appsv1beta1.Rollout, fldPath *field.Path) field.ErrorList {
|
||||
errList := validateRolloutSpecObjectRef(&rollout.Spec.WorkloadRef, fldPath.Child("ObjectRef"))
|
||||
errList = append(errList, validateRolloutRollingStyle(rollout, field.NewPath("RollingStyle"))...)
|
||||
errList = append(errList, validateRolloutSpecStrategy(&rollout.Spec.Strategy, fldPath.Child("Strategy"))...)
|
||||
return errList
|
||||
}
|
||||
|
||||
func validateRolloutRollingStyle(rollout *appsv1beta1.Rollout, fldPath *field.Path) field.ErrorList {
|
||||
workloadRef := rollout.Spec.WorkloadRef
|
||||
if workloadRef.Kind == util.ControllerKindDep.Kind {
|
||||
return nil // Deployment support all rolling styles, no need to validate.
|
||||
}
|
||||
if rollout.Spec.Strategy.Canary.EnableExtraWorkloadForCanary {
|
||||
return field.ErrorList{field.Invalid(fldPath, rollout.Spec.Strategy.Canary.EnableExtraWorkloadForCanary,
|
||||
"Only Deployment can set enableExtraWorkloadForCanary=true")}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateRolloutSpecObjectRef(workloadRef *appsv1beta1.ObjectRef, fldPath *field.Path) field.ErrorList {
|
||||
if workloadRef == nil {
|
||||
return field.ErrorList{field.Invalid(fldPath.Child("WorkloadRef"), workloadRef, "WorkloadRef is required")}
|
||||
|
|
@ -274,13 +261,12 @@ func validateRolloutSpecCanarySteps(steps []appsv1beta1.CanaryStep, fldPath *fie
|
|||
if !isTraffic {
|
||||
continue
|
||||
}
|
||||
if s.Traffic == nil {
|
||||
return field.ErrorList{field.Invalid(fldPath.Index(i).Child("steps"), steps, `traffic cannot be empty`)}
|
||||
}
|
||||
is := intstr.FromString(*s.Traffic)
|
||||
weight, err := intstr.GetScaledValueFromIntOrPercent(&is, 100, true)
|
||||
if err != nil || weight <= 0 || weight > 100 {
|
||||
return field.ErrorList{field.Invalid(fldPath.Index(i).Child("steps"), steps, `traffic must be percentage with "0%" < traffic <= "100%"`)}
|
||||
if s.Traffic != nil {
|
||||
is := intstr.FromString(*s.Traffic)
|
||||
weight, err := intstr.GetScaledValueFromIntOrPercent(&is, 100, true)
|
||||
if err != nil || weight <= 0 || weight > 100 {
|
||||
return field.ErrorList{field.Invalid(fldPath.Index(i).Child("steps"), steps, `traffic must be percentage with "0%" < traffic <= "100%"`)}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -250,8 +250,8 @@ func TestRolloutValidateCreate(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
Name: "Miss matched rolling style",
|
||||
Succeed: false,
|
||||
Name: "matched rolling style",
|
||||
Succeed: true,
|
||||
GetObject: func() []client.Object {
|
||||
object := rollout.DeepCopy()
|
||||
object.Spec.Strategy.Canary.EnableExtraWorkloadForCanary = true
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import (
|
|||
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
|
||||
)
|
||||
|
||||
// +kubebuilder:webhook:path=/validate-rollouts-kruise-io-rollout,mutating=false,failurePolicy=fail,sideEffects=None,admissionReviewVersions=v1;v1beta1,groups=rollouts.kruise.io,resources=rollouts,verbs=create;update,versions=v1alpha1,name=vrollout.kb.io
|
||||
// +kubebuilder:webhook:path=/validate-rollouts-kruise-io-rollout,mutating=false,failurePolicy=fail,sideEffects=None,admissionReviewVersions=v1;v1beta1,groups=rollouts.kruise.io,resources=rollouts,verbs=create;update,versions=v1alpha1;v1beta1,name=vrollout.kb.io
|
||||
|
||||
var (
|
||||
// HandlerMap contains admission webhook handlers
|
||||
|
|
|
|||
|
|
@ -881,6 +881,36 @@ var _ = SIGDescribe("Rollout", func() {
|
|||
By("Creating Rollout...")
|
||||
rollout := &v1alpha1.Rollout{}
|
||||
Expect(ReadYamlToObject("./test_data/rollout/rollout_canary_base.yaml", rollout)).ToNot(HaveOccurred())
|
||||
rollout.Spec.Strategy.Canary.Steps = []v1alpha1.CanaryStep{
|
||||
{
|
||||
TrafficRoutingStrategy: v1alpha1.TrafficRoutingStrategy{
|
||||
Weight: utilpointer.Int32(20),
|
||||
},
|
||||
},
|
||||
{
|
||||
TrafficRoutingStrategy: v1alpha1.TrafficRoutingStrategy{
|
||||
Weight: utilpointer.Int32(40),
|
||||
},
|
||||
},
|
||||
{
|
||||
TrafficRoutingStrategy: v1alpha1.TrafficRoutingStrategy{
|
||||
Weight: utilpointer.Int32(60),
|
||||
},
|
||||
Pause: v1alpha1.RolloutPause{Duration: utilpointer.Int32(10)},
|
||||
},
|
||||
{
|
||||
TrafficRoutingStrategy: v1alpha1.TrafficRoutingStrategy{
|
||||
Weight: utilpointer.Int32(80),
|
||||
},
|
||||
Pause: v1alpha1.RolloutPause{Duration: utilpointer.Int32(10)},
|
||||
},
|
||||
{
|
||||
TrafficRoutingStrategy: v1alpha1.TrafficRoutingStrategy{
|
||||
Weight: utilpointer.Int32(100),
|
||||
},
|
||||
Pause: v1alpha1.RolloutPause{Duration: utilpointer.Int32(1)},
|
||||
},
|
||||
}
|
||||
CreateObject(rollout)
|
||||
|
||||
By("Creating workload and waiting for all pods ready...")
|
||||
|
|
@ -942,8 +972,8 @@ var _ = SIGDescribe("Rollout", func() {
|
|||
|
||||
// resume rollout canary
|
||||
ResumeRolloutCanary(rollout.Name)
|
||||
By("check rollout canary status success, resume rollout, and wait rollout canary complete")
|
||||
time.Sleep(time.Second * 15)
|
||||
// wait step 1 complete
|
||||
WaitRolloutCanaryStepPaused(rollout.Name, 2)
|
||||
|
||||
// v1 -> v2 -> v3, continuous release
|
||||
newEnvs = mergeEnvVar(workload.Spec.Template.Spec.Containers[0].Env, v1.EnvVar{Name: "NODE_NAME", Value: "version3"})
|
||||
|
|
@ -994,6 +1024,9 @@ var _ = SIGDescribe("Rollout", func() {
|
|||
|
||||
// resume rollout canary
|
||||
ResumeRolloutCanary(rollout.Name)
|
||||
// wait step 1 complete
|
||||
WaitRolloutCanaryStepPaused(rollout.Name, 2)
|
||||
ResumeRolloutCanary(rollout.Name)
|
||||
By("check rollout canary status success, resume rollout, and wait rollout canary complete")
|
||||
WaitRolloutStatusPhase(rollout.Name, v1alpha1.RolloutPhaseHealthy)
|
||||
klog.Infof("rollout(%s) completed, and check", namespace)
|
||||
|
|
|
|||
Loading…
Reference in New Issue