feat<rollout>:support time slice and add test
Signed-off-by: MrSumeng <1206834441@qq.com> Signed-off-by: MrSumeng <1206834441@qq.com>
This commit is contained in:
parent
e1ba1b0ea6
commit
df21444717
|
|
@ -31,6 +31,9 @@ type RolloutSpec struct {
|
|||
// Important: Run "make" to regenerate code after modifying this file
|
||||
// ObjectRef indicates workload
|
||||
ObjectRef ObjectRef `json:"objectRef"`
|
||||
//AllowRunTime define allow run time for the rollout
|
||||
//+optional
|
||||
AllowRunTime AllowRunTime `json:"allowRunTime,omitempty"`
|
||||
// rollout strategy
|
||||
Strategy RolloutStrategy `json:"strategy"`
|
||||
// RolloutID should be changed before each workload revision publication.
|
||||
|
|
@ -70,6 +73,33 @@ type WorkloadRef struct {
|
|||
SourceRevisionName string `json:"sourceRevisionName"`
|
||||
}*/
|
||||
|
||||
type AllowRunTime struct {
|
||||
// TimeZone allowed user set the time zone
|
||||
// +optional
|
||||
TimeZone *TimeZone `json:"timeZone,omitempty"`
|
||||
// TimeSlices define some time slices within which the CanaryStrategy is allowed to run in every day
|
||||
// if not define, TimeSlices is all day
|
||||
// +optional
|
||||
TimeSlices []TimeSlice `json:"timeSlices,omitempty"`
|
||||
}
|
||||
|
||||
type TimeZone struct {
|
||||
//Name of the time zone
|
||||
Name string `json:"name"`
|
||||
//Offset
|
||||
// +kubebuilder:validation:Minimum=-43200
|
||||
// +kubebuilder:validation:Maximum=43200
|
||||
Offset int `json:"offset"`
|
||||
}
|
||||
|
||||
//TimeSlice define the start time and end time
|
||||
type TimeSlice struct {
|
||||
//StartTime is this TimeSlice start time
|
||||
StartTime string `json:"startTime"`
|
||||
//EndTime is this TimeSlice end time
|
||||
EndTime string `json:"endTime"`
|
||||
}
|
||||
|
||||
// RolloutStrategy defines strategy to apply during next rollout
|
||||
type RolloutStrategy struct {
|
||||
// Paused indicates that the Rollout is paused.
|
||||
|
|
|
|||
|
|
@ -26,6 +26,31 @@ import (
|
|||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AllowRunTime) DeepCopyInto(out *AllowRunTime) {
|
||||
*out = *in
|
||||
if in.TimeZone != nil {
|
||||
in, out := &in.TimeZone, &out.TimeZone
|
||||
*out = new(TimeZone)
|
||||
**out = **in
|
||||
}
|
||||
if in.TimeSlices != nil {
|
||||
in, out := &in.TimeSlices, &out.TimeSlices
|
||||
*out = make([]TimeSlice, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AllowRunTime.
|
||||
func (in *AllowRunTime) DeepCopy() *AllowRunTime {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AllowRunTime)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *BatchRelease) DeepCopyInto(out *BatchRelease) {
|
||||
*out = *in
|
||||
|
|
@ -428,6 +453,7 @@ func (in *RolloutPause) DeepCopy() *RolloutPause {
|
|||
func (in *RolloutSpec) DeepCopyInto(out *RolloutSpec) {
|
||||
*out = *in
|
||||
in.ObjectRef.DeepCopyInto(&out.ObjectRef)
|
||||
in.AllowRunTime.DeepCopyInto(&out.AllowRunTime)
|
||||
in.Strategy.DeepCopyInto(&out.Strategy)
|
||||
}
|
||||
|
||||
|
|
@ -488,6 +514,36 @@ func (in *RolloutStrategy) DeepCopy() *RolloutStrategy {
|
|||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TimeSlice) DeepCopyInto(out *TimeSlice) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TimeSlice.
|
||||
func (in *TimeSlice) DeepCopy() *TimeSlice {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TimeSlice)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TimeZone) DeepCopyInto(out *TimeZone) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TimeZone.
|
||||
func (in *TimeZone) DeepCopy() *TimeZone {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TimeZone)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TrafficRouting) DeepCopyInto(out *TrafficRouting) {
|
||||
*out = *in
|
||||
|
|
|
|||
|
|
@ -56,6 +56,43 @@ spec:
|
|||
spec:
|
||||
description: RolloutSpec defines the desired state of Rollout
|
||||
properties:
|
||||
allowRunTime:
|
||||
description: AllowRunTime define allow run time for the rollout
|
||||
properties:
|
||||
timeSlices:
|
||||
description: TimeSlices define some time slices within which the
|
||||
CanaryStrategy is allowed to run in every day if not define,
|
||||
TimeSlices is all day
|
||||
items:
|
||||
description: TimeSlice define the start time and end time
|
||||
properties:
|
||||
endTime:
|
||||
description: EndTime is this TimeSlice end time
|
||||
type: string
|
||||
startTime:
|
||||
description: StartTime is this TimeSlice start time
|
||||
type: string
|
||||
required:
|
||||
- endTime
|
||||
- startTime
|
||||
type: object
|
||||
type: array
|
||||
timeZone:
|
||||
description: TimeZone allowed user set the time zone
|
||||
properties:
|
||||
name:
|
||||
description: Name of the time zone
|
||||
type: string
|
||||
offset:
|
||||
description: Offset
|
||||
maximum: 43200
|
||||
minimum: -43200
|
||||
type: integer
|
||||
required:
|
||||
- name
|
||||
- offset
|
||||
type: object
|
||||
type: object
|
||||
objectRef:
|
||||
description: 'INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
|
||||
Important: Run "make" to regenerate code after modifying this file
|
||||
|
|
|
|||
|
|
@ -138,9 +138,28 @@ func (r *rolloutContext) doCanaryUpgrade() (bool, error) {
|
|||
return false, nil
|
||||
}*/
|
||||
|
||||
// verify whether batchRelease configuration is the latest
|
||||
// verify the step run time (now) whether in time slices
|
||||
steps := len(r.rollout.Spec.Strategy.Canary.Steps)
|
||||
canaryStatus := r.newStatus.CanaryStatus
|
||||
cond := util.GetRolloutCondition(*r.newStatus, rolloutv1alpha1.RolloutConditionProgressing)
|
||||
expectedTime, ok := r.isAllowRun(time.Now())
|
||||
if !ok {
|
||||
localTime := expectedTime
|
||||
if &r.rollout.Spec != nil && &r.rollout.Spec.AllowRunTime != nil {
|
||||
localTime.In(util.TimeZone(r.rollout.Spec.AllowRunTime.TimeZone))
|
||||
}
|
||||
msg := fmt.Sprintf("Rollout (%d/%d) will be start at time %s(%s), because now is not in time slices",
|
||||
canaryStatus.CurrentStepIndex, steps,
|
||||
expectedTime.Format(util.DateTimeLayout),
|
||||
localTime.Format(util.DateTimeZoneLayout))
|
||||
klog.Info(msg)
|
||||
cond.Message = msg
|
||||
r.newStatus.Message = cond.Message
|
||||
r.recheckTime = &expectedTime
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// verify whether batchRelease configuration is the latest
|
||||
isLatest, err := r.batchControl.Verify(canaryStatus.CurrentStepIndex)
|
||||
if err != nil {
|
||||
return false, err
|
||||
|
|
@ -158,7 +177,6 @@ func (r *rolloutContext) doCanaryUpgrade() (bool, error) {
|
|||
return false, nil
|
||||
}
|
||||
batchData := util.DumpJSON(batch.Status)
|
||||
cond := util.GetRolloutCondition(*r.newStatus, rolloutv1alpha1.RolloutConditionProgressing)
|
||||
cond.Message = fmt.Sprintf("Rollout is in step(%d/%d), and upgrade workload new versions", canaryStatus.CurrentStepIndex, steps)
|
||||
r.newStatus.Message = cond.Message
|
||||
// promote workload next batch release
|
||||
|
|
|
|||
|
|
@ -108,3 +108,7 @@ func getRolloutID(workload *util.Workload, rollout *rolloutv1alpha1.Rollout) str
|
|||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (r *rolloutContext) isAllowRun(expectedTime time.Time) (time.Time, bool) {
|
||||
return util.TimeInSlice(expectedTime, &r.rollout.Spec.AllowRunTime)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
Copyright 2022 The KubePort Authors.
|
||||
*/
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
rolloutv1alpha1 "github.com/openkruise/rollouts/api/v1alpha1"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
DateTimeZoneLayout = "2006-01-02 15:04:05 MST"
|
||||
DateTimeLayout = "2006-01-02 15:04:05"
|
||||
DateLayout = "2006-01-02"
|
||||
)
|
||||
|
||||
//ValidateTime used to validate _time whether right
|
||||
func ValidateTime(date, _time string, zone *time.Location) (time.Time, error) {
|
||||
if zone == nil {
|
||||
zone = time.Local
|
||||
}
|
||||
if date == "" {
|
||||
date = DateLayout
|
||||
}
|
||||
return time.ParseInLocation(DateTimeLayout, fmt.Sprintf("%s %s", date, _time), zone)
|
||||
}
|
||||
|
||||
func TimeZone(zone *rolloutv1alpha1.TimeZone) *time.Location {
|
||||
if zone != nil {
|
||||
return time.FixedZone(zone.Name, zone.Offset)
|
||||
}
|
||||
return time.Local
|
||||
}
|
||||
|
||||
//TimeInSlice used to validate the expectedTime whether in the timeSlices.
|
||||
//it returns expectedTime and 'false' if the timeSlices is wrong,so you have to make sure the time Slice is correct.
|
||||
//it returns expectedTime and 'true' if the expectedTime is in this timeSlices.
|
||||
//it returns adjacent time and 'false' if the expectedTime is not in this timeSlices.
|
||||
func TimeInSlice(expectedTime time.Time, allowRunTime *rolloutv1alpha1.AllowRunTime) (time.Time, bool) {
|
||||
if allowRunTime == nil {
|
||||
return expectedTime, true
|
||||
}
|
||||
if len(allowRunTime.TimeSlices) == 0 {
|
||||
return expectedTime, true
|
||||
}
|
||||
var (
|
||||
err error
|
||||
start time.Time
|
||||
end time.Time
|
||||
minSub = time.Hour * 48
|
||||
)
|
||||
|
||||
date := expectedTime.Format(DateLayout)
|
||||
timeZone := TimeZone(allowRunTime.TimeZone)
|
||||
|
||||
for i, timeSlice := range allowRunTime.TimeSlices {
|
||||
start, err = ValidateTime(date, timeSlice.StartTime, timeZone)
|
||||
if err != nil {
|
||||
klog.V(5).Infof("timeSlices[%d] StartTime is err %s", i, err.Error())
|
||||
return expectedTime, false
|
||||
}
|
||||
end, err = ValidateTime(date, timeSlice.EndTime, timeZone)
|
||||
if err != nil {
|
||||
klog.V(5).Infof("timeSlices[%d] EndTime is err %s", i, err.Error())
|
||||
return expectedTime, false
|
||||
}
|
||||
|
||||
if expectedTime.After(start) && expectedTime.Before(end) {
|
||||
return expectedTime, true
|
||||
}
|
||||
|
||||
subTime := start.Sub(expectedTime)
|
||||
if subTime < 0 {
|
||||
subTime += time.Hour * 24
|
||||
}
|
||||
if subTime < minSub {
|
||||
minSub = subTime
|
||||
}
|
||||
}
|
||||
return expectedTime.Add(minSub), false
|
||||
}
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
Copyright 2022 The KubePort Authors.
|
||||
*/
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
rolloutv1alpha1 "github.com/openkruise/rollouts/api/v1alpha1"
|
||||
)
|
||||
|
||||
var allowTime = &rolloutv1alpha1.AllowRunTime{
|
||||
TimeZone: nil,
|
||||
TimeSlices: []rolloutv1alpha1.TimeSlice{
|
||||
{
|
||||
StartTime: "00:00:00",
|
||||
EndTime: "2:00:00",
|
||||
},
|
||||
{
|
||||
StartTime: "10:00:00",
|
||||
EndTime: "12:00:00",
|
||||
},
|
||||
{
|
||||
StartTime: "16:00:00",
|
||||
EndTime: "20:00:00",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestTimeInSlice(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
test := []struct {
|
||||
Name string
|
||||
TestTime string
|
||||
ExpectedTime string
|
||||
ExpectedRes bool
|
||||
}{
|
||||
{
|
||||
Name: "in current slice",
|
||||
TestTime: "2022-08-08 1:03:03",
|
||||
ExpectedTime: "2022-08-08 1:03:03",
|
||||
ExpectedRes: true,
|
||||
},
|
||||
{
|
||||
Name: "in current day",
|
||||
TestTime: "2022-08-08 13:00:00",
|
||||
ExpectedTime: "2022-08-08 16:00:00",
|
||||
ExpectedRes: false,
|
||||
},
|
||||
{
|
||||
Name: "in next day",
|
||||
TestTime: "2022-08-08 22:03:03",
|
||||
ExpectedTime: "2022-08-09 00:00:00",
|
||||
ExpectedRes: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, s := range test {
|
||||
t.Run(s.Name, func(t *testing.T) {
|
||||
testTime, _ := time.ParseInLocation(DateTimeLayout, s.TestTime, time.Local)
|
||||
expectedTime, _ := time.ParseInLocation(DateTimeLayout, s.ExpectedTime, time.Local)
|
||||
resTime, res := TimeInSlice(testTime, allowTime)
|
||||
Expect(expectedTime.Unix()).Should(Equal(resTime.Unix()))
|
||||
Expect(s.ExpectedRes).Should(Equal(res))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimeZone(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
test := []struct {
|
||||
name string
|
||||
data *rolloutv1alpha1.TimeZone
|
||||
expect *time.Location
|
||||
}{
|
||||
{
|
||||
name: "local",
|
||||
data: nil,
|
||||
expect: time.Local,
|
||||
},
|
||||
{
|
||||
name: "UTC",
|
||||
data: &rolloutv1alpha1.TimeZone{
|
||||
Name: "UTC",
|
||||
Offset: 28800,
|
||||
},
|
||||
expect: time.FixedZone("UTC", 28800),
|
||||
},
|
||||
}
|
||||
for _, s := range test {
|
||||
t.Run(s.name, func(t *testing.T) {
|
||||
zone := TimeZone(s.data)
|
||||
now := time.Now()
|
||||
Expect(now.In(zone).Unix()).Should(Equal(now.In(s.expect).Unix()))
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestValidateTime(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
test := []struct {
|
||||
name string
|
||||
date string
|
||||
time string
|
||||
expect string
|
||||
}{
|
||||
{
|
||||
name: "right: date not empty",
|
||||
date: "2022-08-08",
|
||||
time: "00:00:00",
|
||||
expect: "2022-08-08 00:00:00",
|
||||
},
|
||||
{
|
||||
name: "right: date is empty",
|
||||
date: "",
|
||||
time: "01:00:00",
|
||||
expect: "2006-01-02 01:00:00",
|
||||
},
|
||||
{
|
||||
name: "wrong: time more then 24h",
|
||||
date: "",
|
||||
time: "25:00:00",
|
||||
},
|
||||
{
|
||||
name: "wrong: time less then 0h",
|
||||
date: "",
|
||||
time: "-01:00:00",
|
||||
},
|
||||
{
|
||||
name: "wrong: time is incomplete",
|
||||
date: "",
|
||||
time: "21:00",
|
||||
},
|
||||
}
|
||||
for _, s := range test {
|
||||
t.Run(s.name, func(t *testing.T) {
|
||||
resTime, err := ValidateTime(s.date, s.time, nil)
|
||||
if s.expect != "" {
|
||||
expectedTime, _ := time.ParseInLocation(DateTimeLayout, s.expect, time.Local)
|
||||
Expect(expectedTime.Unix()).Should(Equal(resTime.Unix()))
|
||||
} else {
|
||||
Expect(len(err.Error()) != 0).Should(BeTrue())
|
||||
t.Log(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -140,6 +140,7 @@ func (h *RolloutCreateUpdateHandler) validateRolloutConflict(rollout *appsv1alph
|
|||
|
||||
func validateRolloutSpec(rollout *appsv1alpha1.Rollout, fldPath *field.Path) field.ErrorList {
|
||||
errList := validateRolloutSpecObjectRef(&rollout.Spec.ObjectRef, fldPath.Child("ObjectRef"))
|
||||
errList = append(errList, validateRolloutSpecAllowRunTime(&rollout.Spec.AllowRunTime, fldPath.Child("AllowRunTime"))...)
|
||||
errList = append(errList, validateRolloutSpecStrategy(&rollout.Spec.Strategy, fldPath.Child("Strategy"))...)
|
||||
return errList
|
||||
}
|
||||
|
|
@ -156,6 +157,35 @@ func validateRolloutSpecObjectRef(objectRef *appsv1alpha1.ObjectRef, fldPath *fi
|
|||
return nil
|
||||
}
|
||||
|
||||
func validateRolloutSpecAllowRunTime(allowRunTime *appsv1alpha1.AllowRunTime, fldPath *field.Path) field.ErrorList {
|
||||
if allowRunTime != nil {
|
||||
return validateRolloutSpecTimeSlices(allowRunTime.TimeSlices, fldPath.Child("TimeSlices"))
|
||||
}
|
||||
return field.ErrorList{}
|
||||
}
|
||||
func validateRolloutSpecTimeSlices(timeSlices []appsv1alpha1.TimeSlice, fldPath *field.Path) field.ErrorList {
|
||||
if len(timeSlices) == 0 {
|
||||
return field.ErrorList{}
|
||||
}
|
||||
errList := field.ErrorList{}
|
||||
for i, t := range timeSlices {
|
||||
//Parse time, TimeDuration need >= 0 && <= 86400
|
||||
start, err := util.ValidateTime("", t.StartTime, nil)
|
||||
if err != nil {
|
||||
return append(errList, field.Invalid(fldPath.Index(i).Child("StartTime"), t.StartTime, err.Error()))
|
||||
}
|
||||
end, err := util.ValidateTime("", t.EndTime, nil)
|
||||
if err != nil {
|
||||
return append(errList, field.Invalid(fldPath.Index(i).Child("EndTime"), t.EndTime, err.Error()))
|
||||
}
|
||||
//startTime need less than endTime
|
||||
if start.After(end) {
|
||||
return append(errList, field.Invalid(fldPath.Index(i).Child("timeRange"), t, "startTime need less then endTime"))
|
||||
}
|
||||
}
|
||||
return errList
|
||||
}
|
||||
|
||||
func validateRolloutSpecStrategy(strategy *appsv1alpha1.RolloutStrategy, fldPath *field.Path) field.ErrorList {
|
||||
return validateRolloutSpecCanaryStrategy(strategy.Canary, fldPath.Child("Canary"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,22 @@ var (
|
|||
Name: "deployment-demo",
|
||||
},
|
||||
},
|
||||
AllowRunTime: appsv1alpha1.AllowRunTime{
|
||||
TimeSlices: []appsv1alpha1.TimeSlice{
|
||||
{
|
||||
StartTime: "00:00:00",
|
||||
EndTime: "2:00:00",
|
||||
},
|
||||
{
|
||||
StartTime: "10:00:00",
|
||||
EndTime: "12:00:00",
|
||||
},
|
||||
{
|
||||
StartTime: "16:00:00",
|
||||
EndTime: "20:00:00",
|
||||
},
|
||||
},
|
||||
},
|
||||
Strategy: appsv1alpha1.RolloutStrategy{
|
||||
Canary: &appsv1alpha1.CanaryStrategy{
|
||||
Steps: []appsv1alpha1.CanaryStep{
|
||||
|
|
@ -95,6 +111,15 @@ func TestRolloutValidateCreate(t *testing.T) {
|
|||
return []client.Object{rollout.DeepCopy()}
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Normal case : time slices is nil",
|
||||
Succeed: true,
|
||||
GetObject: func() []client.Object {
|
||||
object := rollout.DeepCopy()
|
||||
object.Spec.AllowRunTime.TimeSlices = nil
|
||||
return []client.Object{object}
|
||||
},
|
||||
},
|
||||
/***********************************************************
|
||||
The following cases may lead to controller panic
|
||||
**********************************************************/
|
||||
|
|
@ -119,6 +144,44 @@ func TestRolloutValidateCreate(t *testing.T) {
|
|||
/****************************************************************
|
||||
The following cases may lead to that controller cannot work
|
||||
***************************************************************/
|
||||
{
|
||||
Name: "TimeSlices time is empty",
|
||||
Succeed: false,
|
||||
GetObject: func() []client.Object {
|
||||
object := rollout.DeepCopy()
|
||||
object.Spec.AllowRunTime.TimeSlices[0].StartTime = ""
|
||||
object.Spec.AllowRunTime.TimeSlices[0].EndTime = ""
|
||||
return []client.Object{object}
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "TimeSlices time is incomplete",
|
||||
Succeed: false,
|
||||
GetObject: func() []client.Object {
|
||||
object := rollout.DeepCopy()
|
||||
object.Spec.AllowRunTime.TimeSlices[0].StartTime = "00:00"
|
||||
return []client.Object{object}
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "TimeSlices start time more than end time",
|
||||
Succeed: false,
|
||||
GetObject: func() []client.Object {
|
||||
object := rollout.DeepCopy()
|
||||
object.Spec.AllowRunTime.TimeSlices[0].StartTime = "02:00:00"
|
||||
object.Spec.AllowRunTime.TimeSlices[0].EndTime = "00:00:00"
|
||||
return []client.Object{object}
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "TimeSlices time out of range",
|
||||
Succeed: false,
|
||||
GetObject: func() []client.Object {
|
||||
object := rollout.DeepCopy()
|
||||
object.Spec.AllowRunTime.TimeSlices[0].EndTime = "26:00:00"
|
||||
return []client.Object{object}
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Service name is empty",
|
||||
Succeed: false,
|
||||
|
|
|
|||
Loading…
Reference in New Issue