Merge pull request #3437 from Poor12/add-deleteOption-for-tasks

Add GracePeriodSeconds for GracefulEvictionTask
This commit is contained in:
karmada-bot 2023-04-24 16:28:16 +08:00 committed by GitHub
commit effd5f8f81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 369 additions and 3 deletions

View File

@ -15048,6 +15048,11 @@
"default": {},
"$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.policy.v1alpha1.DecisionConditions"
},
"gracePeriodSeconds": {
"description": "GracePeriodSeconds is the maximum waiting duration in seconds before application on the migrated cluster should be deleted. Required only when PurgeMode is \"Graciously\" and defaults to 600s. If the application on the new cluster cannot reach a Healthy state, Karmada will delete the application after GracePeriodSeconds is reached. Value must be positive integer.",
"type": "integer",
"format": "int32"
},
"preConditions": {
"description": "PreConditions indicates the preconditions of the failover process. If specified, only when all conditions are met can the failover process be started. Currently, PreConditions includes several conditions: - DelaySeconds (optional) - HealthyState (optional)",
"$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.policy.v1alpha1.PreConditions"
@ -16564,6 +16569,11 @@
"type": "string",
"default": ""
},
"gracePeriodSeconds": {
"description": "GracePeriodSeconds is the maximum waiting duration in seconds before the item should be deleted. If the application on the new cluster cannot reach a Healthy state, Karmada will delete the item after GracePeriodSeconds is reached. Value must be positive integer. It can not co-exist with SuppressDeletion.",
"type": "integer",
"format": "int32"
},
"message": {
"description": "Message is a human-readable message indicating details about the eviction. This may be an empty string.",
"type": "string"
@ -16582,6 +16592,10 @@
"description": "Replicas indicates the number of replicas should be evicted. Should be ignored for resource type that doesn't have replica.",
"type": "integer",
"format": "int32"
},
"suppressDeletion": {
"description": "SuppressDeletion represents the grace period will be persistent until the tools or human intervention stops it. It can not co-exist with GracePeriodSeconds.",
"type": "boolean"
}
}
},

View File

@ -99,6 +99,16 @@ spec:
format: int32
type: integer
type: object
gracePeriodSeconds:
description: GracePeriodSeconds is the maximum waiting duration
in seconds before application on the migrated cluster should
be deleted. Required only when PurgeMode is "Graciously"
and defaults to 600s. If the application on the new cluster
cannot reach a Healthy state, Karmada will delete the application
after GracePeriodSeconds is reached. Value must be positive
integer.
format: int32
type: integer
preConditions:
description: 'PreConditions indicates the preconditions of
the failover process. If specified, only when all conditions

View File

@ -95,6 +95,16 @@ spec:
format: int32
type: integer
type: object
gracePeriodSeconds:
description: GracePeriodSeconds is the maximum waiting duration
in seconds before application on the migrated cluster should
be deleted. Required only when PurgeMode is "Graciously"
and defaults to 600s. If the application on the new cluster
cannot reach a Healthy state, Karmada will delete the application
after GracePeriodSeconds is reached. Value must be positive
integer.
format: int32
type: integer
preConditions:
description: 'PreConditions indicates the preconditions of
the failover process. If specified, only when all conditions

View File

@ -303,6 +303,16 @@ spec:
format: int32
type: integer
type: object
gracePeriodSeconds:
description: GracePeriodSeconds is the maximum waiting duration
in seconds before application on the migrated cluster should
be deleted. Required only when PurgeMode is "Graciously"
and defaults to 600s. If the application on the new cluster
cannot reach a Healthy state, Karmada will delete the application
after GracePeriodSeconds is reached. Value must be positive
integer.
format: int32
type: integer
preConditions:
description: 'PreConditions indicates the preconditions of
the failover process. If specified, only when all conditions
@ -368,6 +378,14 @@ spec:
description: FromCluster which cluster the eviction perform
from.
type: string
gracePeriodSeconds:
description: GracePeriodSeconds is the maximum waiting duration
in seconds before the item should be deleted. If the application
on the new cluster cannot reach a Healthy state, Karmada will
delete the item after GracePeriodSeconds is reached. Value
must be positive integer. It can not co-exist with SuppressDeletion.
format: int32
type: integer
message:
description: Message is a human-readable message indicating
details about the eviction. This may be an empty string.
@ -393,6 +411,11 @@ spec:
have replica.
format: int32
type: integer
suppressDeletion:
description: SuppressDeletion represents the grace period will
be persistent until the tools or human intervention stops
it. It can not co-exist with GracePeriodSeconds.
type: boolean
required:
- fromCluster
- producer

View File

@ -303,6 +303,16 @@ spec:
format: int32
type: integer
type: object
gracePeriodSeconds:
description: GracePeriodSeconds is the maximum waiting duration
in seconds before application on the migrated cluster should
be deleted. Required only when PurgeMode is "Graciously"
and defaults to 600s. If the application on the new cluster
cannot reach a Healthy state, Karmada will delete the application
after GracePeriodSeconds is reached. Value must be positive
integer.
format: int32
type: integer
preConditions:
description: 'PreConditions indicates the preconditions of
the failover process. If specified, only when all conditions
@ -368,6 +378,14 @@ spec:
description: FromCluster which cluster the eviction perform
from.
type: string
gracePeriodSeconds:
description: GracePeriodSeconds is the maximum waiting duration
in seconds before the item should be deleted. If the application
on the new cluster cannot reach a Healthy state, Karmada will
delete the item after GracePeriodSeconds is reached. Value
must be positive integer. It can not co-exist with SuppressDeletion.
format: int32
type: integer
message:
description: Message is a human-readable message indicating
details about the eviction. This may be an empty string.
@ -393,6 +411,11 @@ spec:
have replica.
format: int32
type: integer
suppressDeletion:
description: SuppressDeletion represents the grace period will
be persistent until the tools or human intervention stops
it. It can not co-exist with GracePeriodSeconds.
type: boolean
required:
- fromCluster
- producer

View File

@ -221,6 +221,15 @@ type ApplicationFailoverBehavior struct {
// +optional
PurgeMode PurgeMode `json:"purgeMode,omitempty"`
// GracePeriodSeconds is the maximum waiting duration in seconds before
// application on the migrated cluster should be deleted.
// Required only when PurgeMode is "Graciously" and defaults to 600s.
// If the application on the new cluster cannot reach a Healthy state,
// Karmada will delete the application after GracePeriodSeconds is reached.
// Value must be positive integer.
// +optional
GracePeriodSeconds *int32 `json:"gracePeriodSeconds,omitempty"`
// BlockPredecessorSeconds represents the period of time the cluster from which the
// application was migrated from can be schedulable again.
// During the period of BlockPredecessorSeconds, clusters are forcibly filtered out by the scheduler.

View File

@ -20,6 +20,11 @@ func (in *ApplicationFailoverBehavior) DeepCopyInto(out *ApplicationFailoverBeha
(*in).DeepCopyInto(*out)
}
in.DecisionConditions.DeepCopyInto(&out.DecisionConditions)
if in.GracePeriodSeconds != nil {
in, out := &in.GracePeriodSeconds, &out.GracePeriodSeconds
*out = new(int32)
**out = **in
}
if in.BlockPredecessorSeconds != nil {
in, out := &in.BlockPredecessorSeconds, &out.BlockPredecessorSeconds
*out = new(int32)

View File

@ -206,6 +206,20 @@ type GracefulEvictionTask struct {
// +required
Producer string `json:"producer"`
// GracePeriodSeconds is the maximum waiting duration in seconds before the item
// should be deleted. If the application on the new cluster cannot reach a Healthy state,
// Karmada will delete the item after GracePeriodSeconds is reached.
// Value must be positive integer.
// It can not co-exist with SuppressDeletion.
// +optional
GracePeriodSeconds *int32 `json:"gracePeriodSeconds,omitempty"`
// SuppressDeletion represents the grace period will be persistent until
// the tools or human intervention stops it.
// It can not co-exist with GracePeriodSeconds.
// +optional
SuppressDeletion *bool `json:"suppressDeletion,omitempty"`
// CreationTimestamp is a timestamp representing the server time when this object was
// created.
// Clients should not set this value to avoid the time inconsistency issue.

View File

@ -123,6 +123,16 @@ func (in *GracefulEvictionTask) DeepCopyInto(out *GracefulEvictionTask) {
*out = new(int32)
**out = **in
}
if in.GracePeriodSeconds != nil {
in, out := &in.GracePeriodSeconds, &out.GracePeriodSeconds
*out = new(int32)
**out = **in
}
if in.SuppressDeletion != nil {
in, out := &in.SuppressDeletion, &out.SuppressDeletion
*out = new(bool)
**out = **in
}
in.CreationTimestamp.DeepCopyInto(&out.CreationTimestamp)
return
}

View File

@ -48,8 +48,22 @@ func assessEvictionTasks(bindingSpec workv1alpha2.ResourceBindingSpec,
}
func assessSingleTask(task workv1alpha2.GracefulEvictionTask, opt assessmentOption) *workv1alpha2.GracefulEvictionTask {
if task.SuppressDeletion != nil {
if *task.SuppressDeletion {
return &task
}
// If *task.SuppressDeletion is equal to false,
// it means users have confirmed that they want to delete the redundant copy.
// In that case, we will delete the task immediately.
return nil
}
timeout := opt.timeout
if task.GracePeriodSeconds != nil {
timeout = time.Duration(*task.GracePeriodSeconds) * time.Second
}
// task exceeds timeout
if metav1.Now().After(task.CreationTimestamp.Add(opt.timeout)) {
if metav1.Now().After(task.CreationTimestamp.Add(timeout)) {
return nil
}
@ -94,6 +108,9 @@ func nextRetry(tasks []workv1alpha2.GracefulEvictionTask, timeout time.Duration,
retryInterval := timeout / 10
for i := range tasks {
if tasks[i].GracePeriodSeconds != nil {
timeout = time.Duration(*tasks[i].GracePeriodSeconds) * time.Second
}
next := tasks[i].CreationTimestamp.Add(timeout).Sub(timeNow)
if next < retryInterval {
retryInterval = next

View File

@ -6,6 +6,7 @@ import (
"time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/pointer"
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
)
@ -121,6 +122,94 @@ func Test_assessSingleTask(t *testing.T) {
CreationTimestamp: metav1.Time{Time: timeNow.Add(time.Minute * -1)},
},
},
{
name: "gracePeriodSeconds is declared in gracefulEvictionTask and timeout is not reached",
args: args{
task: workv1alpha2.GracefulEvictionTask{
FromCluster: "member1",
GracePeriodSeconds: pointer.Int32(30),
CreationTimestamp: metav1.Time{Time: timeNow.Add(time.Minute * -1)},
},
opt: assessmentOption{
timeout: timeout,
scheduleResult: []workv1alpha2.TargetCluster{
{Name: "memberA"},
},
observedStatus: []workv1alpha2.AggregatedStatusItem{
{ClusterName: "memberA", Health: workv1alpha2.ResourceUnknown},
},
},
},
want: nil,
},
{
name: "gracePeriodSeconds is declared in gracefulEvictionTask and timeout is reached",
args: args{
task: workv1alpha2.GracefulEvictionTask{
FromCluster: "member1",
GracePeriodSeconds: pointer.Int32(120),
CreationTimestamp: metav1.Time{Time: timeNow.Add(time.Minute * -1)},
},
opt: assessmentOption{
timeout: timeout,
scheduleResult: []workv1alpha2.TargetCluster{
{Name: "memberA"},
},
observedStatus: []workv1alpha2.AggregatedStatusItem{
{ClusterName: "memberA", Health: workv1alpha2.ResourceUnknown},
},
},
},
want: &workv1alpha2.GracefulEvictionTask{
FromCluster: "member1",
GracePeriodSeconds: pointer.Int32(120),
CreationTimestamp: metav1.Time{Time: timeNow.Add(time.Minute * -1)},
},
},
{
name: "suppressDeletion is declared in gracefulEvictionTask and is true",
args: args{
task: workv1alpha2.GracefulEvictionTask{
FromCluster: "member1",
SuppressDeletion: pointer.Bool(true),
CreationTimestamp: metav1.Time{Time: timeNow.Add(time.Minute * -1)},
},
opt: assessmentOption{
timeout: timeout,
scheduleResult: []workv1alpha2.TargetCluster{
{Name: "memberA"},
},
observedStatus: []workv1alpha2.AggregatedStatusItem{
{ClusterName: "memberA", Health: workv1alpha2.ResourceHealthy},
},
},
},
want: &workv1alpha2.GracefulEvictionTask{
FromCluster: "member1",
SuppressDeletion: pointer.Bool(true),
CreationTimestamp: metav1.Time{Time: timeNow.Add(time.Minute * -1)},
},
},
{
name: "suppressDeletion is declared in gracefulEvictionTask and is false",
args: args{
task: workv1alpha2.GracefulEvictionTask{
FromCluster: "member1",
SuppressDeletion: pointer.Bool(false),
CreationTimestamp: metav1.Time{Time: timeNow.Add(time.Minute * -1)},
},
opt: assessmentOption{
timeout: timeout,
scheduleResult: []workv1alpha2.TargetCluster{
{Name: "memberA"},
},
observedStatus: []workv1alpha2.AggregatedStatusItem{
{ClusterName: "memberA", Health: workv1alpha2.ResourceHealthy},
},
},
},
want: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

View File

@ -416,6 +416,7 @@ func (d *ResourceDetector) ApplyPolicy(object *unstructured.Unstructured, object
bindingCopy.Spec.PropagateDeps = binding.Spec.PropagateDeps
bindingCopy.Spec.SchedulerName = binding.Spec.SchedulerName
bindingCopy.Spec.Placement = binding.Spec.Placement
bindingCopy.Spec.Failover = binding.Spec.Failover
return nil
})
if err != nil {
@ -491,6 +492,7 @@ func (d *ResourceDetector) ApplyClusterPolicy(object *unstructured.Unstructured,
bindingCopy.Spec.PropagateDeps = binding.Spec.PropagateDeps
bindingCopy.Spec.SchedulerName = binding.Spec.SchedulerName
bindingCopy.Spec.Placement = binding.Spec.Placement
bindingCopy.Spec.Failover = binding.Spec.Failover
return nil
})
if err != nil {
@ -534,6 +536,7 @@ func (d *ResourceDetector) ApplyClusterPolicy(object *unstructured.Unstructured,
bindingCopy.Spec.Replicas = binding.Spec.Replicas
bindingCopy.Spec.SchedulerName = binding.Spec.SchedulerName
bindingCopy.Spec.Placement = binding.Spec.Placement
bindingCopy.Spec.Failover = binding.Spec.Failover
return nil
})
if err != nil {
@ -632,6 +635,7 @@ func (d *ResourceDetector) BuildResourceBinding(object *unstructured.Unstructure
PropagateDeps: policySpec.PropagateDeps,
SchedulerName: policySpec.SchedulerName,
Placement: &policySpec.Placement,
Failover: policySpec.Failover,
Resource: workv1alpha2.ObjectReference{
APIVersion: object.GetAPIVersion(),
Kind: object.GetKind(),
@ -672,6 +676,7 @@ func (d *ResourceDetector) BuildClusterResourceBinding(object *unstructured.Unst
PropagateDeps: policySpec.PropagateDeps,
SchedulerName: policySpec.SchedulerName,
Placement: &policySpec.Placement,
Failover: policySpec.Failover,
Resource: workv1alpha2.ObjectReference{
APIVersion: object.GetAPIVersion(),
Kind: object.GetKind(),

View File

@ -2176,6 +2176,13 @@ func schema_pkg_apis_policy_v1alpha1_ApplicationFailoverBehavior(ref common.Refe
Format: "",
},
},
"gracePeriodSeconds": {
SchemaProps: spec.SchemaProps{
Description: "GracePeriodSeconds is the maximum waiting duration in seconds before application on the migrated cluster should be deleted. Required only when PurgeMode is \"Graciously\" and defaults to 600s. If the application on the new cluster cannot reach a Healthy state, Karmada will delete the application after GracePeriodSeconds is reached. Value must be positive integer.",
Type: []string{"integer"},
Format: "int32",
},
},
"blockPredecessorSeconds": {
SchemaProps: spec.SchemaProps{
Description: "BlockPredecessorSeconds represents the period of time the cluster from which the application was migrated from can be schedulable again. During the period of BlockPredecessorSeconds, clusters are forcibly filtered out by the scheduler. If not specified or the value is zero, the evicted cluster is schedulable to the application when rescheduling. Defaults to 600s.",
@ -5101,6 +5108,20 @@ func schema_pkg_apis_work_v1alpha2_GracefulEvictionTask(ref common.ReferenceCall
Format: "",
},
},
"gracePeriodSeconds": {
SchemaProps: spec.SchemaProps{
Description: "GracePeriodSeconds is the maximum waiting duration in seconds before the item should be deleted. If the application on the new cluster cannot reach a Healthy state, Karmada will delete the item after GracePeriodSeconds is reached. Value must be positive integer. It can not co-exist with SuppressDeletion.",
Type: []string{"integer"},
Format: "int32",
},
},
"suppressDeletion": {
SchemaProps: spec.SchemaProps{
Description: "SuppressDeletion represents the grace period will be persistent until the tools or human intervention stops it. It can not co-exist with GracePeriodSeconds.",
Type: []string{"boolean"},
Format: "",
},
},
"creationTimestamp": {
SchemaProps: spec.SchemaProps{
Description: "CreationTimestamp is a timestamp representing the server time when this object was created. Clients should not set this value to avoid the time inconsistency issue. It is represented in RFC3339 form(like '2021-04-25T10:02:10Z') and is in UTC.\n\nPopulated by the system. Read-only.",

View File

@ -6,6 +6,7 @@ import (
discoveryv1 "k8s.io/api/discovery/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/klog/v2"
"k8s.io/utils/pointer"
"sigs.k8s.io/controller-runtime/pkg/client"
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
@ -132,10 +133,17 @@ func GetAppliedPlacement(annotations map[string]string) (*policyv1alpha1.Placeme
return placement, nil
}
// SetReplicaDivisionPreferenceWeighted Set the default value of ReplicaDivisionPreference to Weighted
// SetReplicaDivisionPreferenceWeighted sets the default value of ReplicaDivisionPreference to Weighted
func SetReplicaDivisionPreferenceWeighted(placement *policyv1alpha1.Placement) {
if placement.ReplicaSchedulingType() != policyv1alpha1.ReplicaSchedulingTypeDivided || placement.ReplicaScheduling.ReplicaDivisionPreference != "" {
return
}
placement.ReplicaScheduling.ReplicaDivisionPreference = policyv1alpha1.ReplicaDivisionPreferenceWeighted
}
// SetDefaultGracePeriodSeconds sets the default value of GracePeriodSeconds in ApplicationFailoverBehavior
func SetDefaultGracePeriodSeconds(behavior *policyv1alpha1.ApplicationFailoverBehavior) {
if behavior.PurgeMode == policyv1alpha1.Graciously && behavior.GracePeriodSeconds == nil {
behavior.GracePeriodSeconds = pointer.Int32(600)
}
}

View File

@ -7,6 +7,7 @@ import (
discoveryv1 "k8s.io/api/discovery/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/pointer"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
@ -400,3 +401,51 @@ func TestSetReplicaDivisionPreferenceWeighted(t *testing.T) {
})
}
}
func TestSetDefaultGracePeriodSeconds(t *testing.T) {
tests := []struct {
name string
behavior *policyv1alpha1.ApplicationFailoverBehavior
expectBehavior *policyv1alpha1.ApplicationFailoverBehavior
}{
{
name: "purgeMode is not graciously",
behavior: &policyv1alpha1.ApplicationFailoverBehavior{
PurgeMode: policyv1alpha1.Never,
},
expectBehavior: &policyv1alpha1.ApplicationFailoverBehavior{
PurgeMode: policyv1alpha1.Never,
},
},
{
name: "purgeMode is graciously and gracePeriodSeconds is set",
behavior: &policyv1alpha1.ApplicationFailoverBehavior{
PurgeMode: policyv1alpha1.Graciously,
GracePeriodSeconds: pointer.Int32(200),
},
expectBehavior: &policyv1alpha1.ApplicationFailoverBehavior{
PurgeMode: policyv1alpha1.Graciously,
GracePeriodSeconds: pointer.Int32(200),
},
},
{
name: "purgeMode is graciously and gracePeriodSeconds is not set",
behavior: &policyv1alpha1.ApplicationFailoverBehavior{
PurgeMode: policyv1alpha1.Graciously,
},
expectBehavior: &policyv1alpha1.ApplicationFailoverBehavior{
PurgeMode: policyv1alpha1.Graciously,
GracePeriodSeconds: pointer.Int32(600),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
SetDefaultGracePeriodSeconds(tt.behavior)
if !reflect.DeepEqual(tt.behavior, tt.expectBehavior) {
t.Errorf("expectedBehavior %v, but got %v", tt.expectBehavior, tt.behavior)
}
})
}
}

View File

@ -176,6 +176,18 @@ func ValidateApplicationFailover(applicationFailoverBehavior *policyv1alpha1.App
allErrs = append(allErrs, field.Invalid(fldPath.Child("blockPredecessorSeconds"), *applicationFailoverBehavior.BlockPredecessorSeconds, "must be greater than or equal to 0"))
}
if applicationFailoverBehavior.PurgeMode != policyv1alpha1.Graciously && applicationFailoverBehavior.GracePeriodSeconds != nil {
allErrs = append(allErrs, field.Invalid(fldPath.Child("gracePeriodSeconds"), *applicationFailoverBehavior.GracePeriodSeconds, "only takes effect when purgeMode is graciously"))
}
if applicationFailoverBehavior.PurgeMode == policyv1alpha1.Graciously && applicationFailoverBehavior.GracePeriodSeconds == nil {
allErrs = append(allErrs, field.Invalid(fldPath.Child("gracePeriodSeconds"), applicationFailoverBehavior.GracePeriodSeconds, "should not be empty when purgeMode is graciously"))
}
if applicationFailoverBehavior.GracePeriodSeconds != nil && *applicationFailoverBehavior.GracePeriodSeconds <= 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("gracePeriodSeconds"), *applicationFailoverBehavior.GracePeriodSeconds, "must be greater than 0"))
}
return allErrs
}

View File

@ -602,7 +602,42 @@ func TestValidateApplicationFailover(t *testing.T) {
expectedErr: "spec.failover.application.blockPredecessorSeconds: Invalid value: -100: must be greater than or equal to 0",
},
{
name: "application behavior is correctly defined",
name: "the gracePeriodSeconds is declared when purgeMode is not graciously",
applicationFailoverBehavior: &policyv1alpha1.ApplicationFailoverBehavior{
BlockPredecessorSeconds: pointer.Int32(100),
DecisionConditions: policyv1alpha1.DecisionConditions{
TolerationSeconds: pointer.Int32(100),
},
PurgeMode: policyv1alpha1.Immediately,
GracePeriodSeconds: pointer.Int32(100),
},
expectedErr: "spec.failover.application.gracePeriodSeconds: Invalid value: 100: only takes effect when purgeMode is graciously",
},
{
name: "the gracePeriodSeconds is less than 0 when purgeMode is graciously",
applicationFailoverBehavior: &policyv1alpha1.ApplicationFailoverBehavior{
BlockPredecessorSeconds: pointer.Int32(100),
DecisionConditions: policyv1alpha1.DecisionConditions{
TolerationSeconds: pointer.Int32(100),
},
PurgeMode: policyv1alpha1.Graciously,
GracePeriodSeconds: pointer.Int32(-100),
},
expectedErr: "spec.failover.application.gracePeriodSeconds: Invalid value: -100: must be greater than 0",
},
{
name: "the gracePeriodSeconds is empty when purgeMode is graciously",
applicationFailoverBehavior: &policyv1alpha1.ApplicationFailoverBehavior{
BlockPredecessorSeconds: pointer.Int32(100),
DecisionConditions: policyv1alpha1.DecisionConditions{
TolerationSeconds: pointer.Int32(100),
},
PurgeMode: policyv1alpha1.Graciously,
},
expectedErr: "spec.failover.application.gracePeriodSeconds: Invalid value: \"null\": should not be empty when purgeMode is graciously",
},
{
name: "application behavior is correctly declared",
applicationFailoverBehavior: &policyv1alpha1.ApplicationFailoverBehavior{
BlockPredecessorSeconds: pointer.Int32(100),
DecisionConditions: policyv1alpha1.DecisionConditions{

View File

@ -59,6 +59,12 @@ func (a *MutatingAdmission) Handle(ctx context.Context, req admission.Request) a
// When ReplicaSchedulingType is Divided, set the default value of ReplicaDivisionPreference to Weighted.
helper.SetReplicaDivisionPreferenceWeighted(&policy.Spec.Placement)
if policy.Spec.Failover != nil {
if policy.Spec.Failover.Application != nil {
helper.SetDefaultGracePeriodSeconds(policy.Spec.Failover.Application)
}
}
marshaledBytes, err := json.Marshal(policy)
if err != nil {
return admission.Errored(http.StatusInternalServerError, err)

View File

@ -71,6 +71,12 @@ func (a *MutatingAdmission) Handle(ctx context.Context, req admission.Request) a
// When ReplicaSchedulingType is Divided, set the default value of ReplicaDivisionPreference to Weighted.
helper.SetReplicaDivisionPreferenceWeighted(&policy.Spec.Placement)
if policy.Spec.Failover != nil {
if policy.Spec.Failover.Application != nil {
helper.SetDefaultGracePeriodSeconds(policy.Spec.Failover.Application)
}
}
marshaledBytes, err := json.Marshal(policy)
if err != nil {
return admission.Errored(http.StatusInternalServerError, err)