Merge pull request #3437 from Poor12/add-deleteOption-for-tasks
Add GracePeriodSeconds for GracefulEvictionTask
This commit is contained in:
commit
effd5f8f81
|
@ -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"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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.",
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue