Merge pull request #119026 from AxeZhan/sleepAction

Introducing Sleep Action for PreStop Hook
This commit is contained in:
Kubernetes Prow Robot 2023-10-16 21:19:44 +02:00 committed by GitHub
commit f6ba25fdbd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
81 changed files with 2331 additions and 994 deletions

View File

@ -7006,6 +7006,10 @@
"$ref": "#/definitions/io.k8s.api.core.v1.HTTPGetAction",
"description": "HTTPGet specifies the http request to perform."
},
"sleep": {
"$ref": "#/definitions/io.k8s.api.core.v1.SleepAction",
"description": "Sleep represents the duration that the container should sleep before being terminated."
},
"tcpSocket": {
"$ref": "#/definitions/io.k8s.api.core.v1.TCPSocketAction",
"description": "Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept for the backward compatibility. There are no validation of this field and lifecycle hooks will fail in runtime when tcp handler is specified."
@ -10435,6 +10439,20 @@
},
"type": "object"
},
"io.k8s.api.core.v1.SleepAction": {
"description": "SleepAction describes a \"sleep\" action.",
"properties": {
"seconds": {
"description": "Seconds is the number of seconds to sleep.",
"format": "int64",
"type": "integer"
}
},
"required": [
"seconds"
],
"type": "object"
},
"io.k8s.api.core.v1.StorageOSPersistentVolumeSource": {
"description": "Represents a StorageOS persistent volume resource.",
"properties": {

View File

@ -2901,6 +2901,14 @@
],
"description": "HTTPGet specifies the http request to perform."
},
"sleep": {
"allOf": [
{
"$ref": "#/components/schemas/io.k8s.api.core.v1.SleepAction"
}
],
"description": "Sleep represents the duration that the container should sleep before being terminated."
},
"tcpSocket": {
"allOf": [
{
@ -7357,6 +7365,21 @@
},
"type": "object"
},
"io.k8s.api.core.v1.SleepAction": {
"description": "SleepAction describes a \"sleep\" action.",
"properties": {
"seconds": {
"default": 0,
"description": "Seconds is the number of seconds to sleep.",
"format": "int64",
"type": "integer"
}
},
"required": [
"seconds"
],
"type": "object"
},
"io.k8s.api.core.v1.StorageOSPersistentVolumeSource": {
"description": "Represents a StorageOS persistent volume resource.",
"properties": {

View File

@ -2760,6 +2760,14 @@
],
"description": "HTTPGet specifies the http request to perform."
},
"sleep": {
"allOf": [
{
"$ref": "#/components/schemas/io.k8s.api.core.v1.SleepAction"
}
],
"description": "Sleep represents the duration that the container should sleep before being terminated."
},
"tcpSocket": {
"allOf": [
{
@ -4438,6 +4446,21 @@
],
"type": "object"
},
"io.k8s.api.core.v1.SleepAction": {
"description": "SleepAction describes a \"sleep\" action.",
"properties": {
"seconds": {
"default": 0,
"description": "Seconds is the number of seconds to sleep.",
"format": "int64",
"type": "integer"
}
},
"required": [
"seconds"
],
"type": "object"
},
"io.k8s.api.core.v1.StorageOSVolumeSource": {
"description": "Represents a StorageOS persistent volume resource.",
"properties": {

View File

@ -2073,6 +2073,14 @@
],
"description": "HTTPGet specifies the http request to perform."
},
"sleep": {
"allOf": [
{
"$ref": "#/components/schemas/io.k8s.api.core.v1.SleepAction"
}
],
"description": "Sleep represents the duration that the container should sleep before being terminated."
},
"tcpSocket": {
"allOf": [
{
@ -3629,6 +3637,21 @@
],
"type": "object"
},
"io.k8s.api.core.v1.SleepAction": {
"description": "SleepAction describes a \"sleep\" action.",
"properties": {
"seconds": {
"default": 0,
"description": "Seconds is the number of seconds to sleep.",
"format": "int64",
"type": "integer"
}
},
"required": [
"seconds"
],
"type": "object"
},
"io.k8s.api.core.v1.StorageOSVolumeSource": {
"description": "Represents a StorageOS persistent volume resource.",
"properties": {

View File

@ -558,6 +558,64 @@ func dropDisabledFields(
}
// For other types of containers, validateContainers will handle them.
}
if !utilfeature.DefaultFeatureGate.Enabled(features.PodLifecycleSleepAction) && !podLifecycleSleepActionInUse(oldPodSpec) {
for i := range podSpec.Containers {
if podSpec.Containers[i].Lifecycle == nil {
continue
}
if podSpec.Containers[i].Lifecycle.PreStop != nil {
podSpec.Containers[i].Lifecycle.PreStop.Sleep = nil
}
if podSpec.Containers[i].Lifecycle.PostStart != nil {
podSpec.Containers[i].Lifecycle.PostStart.Sleep = nil
}
}
for i := range podSpec.InitContainers {
if podSpec.InitContainers[i].Lifecycle == nil {
continue
}
if podSpec.InitContainers[i].Lifecycle.PreStop != nil {
podSpec.InitContainers[i].Lifecycle.PreStop.Sleep = nil
}
if podSpec.InitContainers[i].Lifecycle.PostStart != nil {
podSpec.InitContainers[i].Lifecycle.PostStart.Sleep = nil
}
}
for i := range podSpec.EphemeralContainers {
if podSpec.EphemeralContainers[i].Lifecycle == nil {
continue
}
if podSpec.EphemeralContainers[i].Lifecycle.PreStop != nil {
podSpec.EphemeralContainers[i].Lifecycle.PreStop.Sleep = nil
}
if podSpec.EphemeralContainers[i].Lifecycle.PostStart != nil {
podSpec.EphemeralContainers[i].Lifecycle.PostStart.Sleep = nil
}
}
}
}
func podLifecycleSleepActionInUse(podSpec *api.PodSpec) bool {
if podSpec == nil {
return false
}
var inUse bool
VisitContainers(podSpec, AllContainers, func(c *api.Container, containerType ContainerType) bool {
if c.Lifecycle == nil {
return true
}
if c.Lifecycle.PreStop != nil && c.Lifecycle.PreStop.Sleep != nil {
inUse = true
return false
}
if c.Lifecycle.PostStart != nil && c.Lifecycle.PostStart.Sleep != nil {
inUse = true
return false
}
return true
})
return inUse
}
// dropDisabledPodStatusFields removes disabled fields from the pod status

View File

@ -2150,6 +2150,12 @@ type ExecAction struct {
Command []string
}
// SleepAction describes a "sleep" action.
type SleepAction struct {
// Seconds is the number of seconds to sleep.
Seconds int64
}
// Probe describes a health check to be performed against a container to determine whether it is
// alive or ready to receive traffic.
type Probe struct {
@ -2432,6 +2438,10 @@ type LifecycleHandler struct {
// lifecycle hooks will fail in runtime when tcp handler is specified.
// +optional
TCPSocket *TCPSocketAction
// Sleep represents the duration that the container should sleep before being terminated.
// +featureGate=PodLifecycleSleepAction
// +optional
Sleep *SleepAction
}
type GRPCAction struct {

View File

@ -1937,6 +1937,16 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1.SleepAction)(nil), (*core.SleepAction)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_SleepAction_To_core_SleepAction(a.(*v1.SleepAction), b.(*core.SleepAction), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*core.SleepAction)(nil), (*v1.SleepAction)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_core_SleepAction_To_v1_SleepAction(a.(*core.SleepAction), b.(*v1.SleepAction), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1.StorageOSPersistentVolumeSource)(nil), (*core.StorageOSPersistentVolumeSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_StorageOSPersistentVolumeSource_To_core_StorageOSPersistentVolumeSource(a.(*v1.StorageOSPersistentVolumeSource), b.(*core.StorageOSPersistentVolumeSource), scope)
}); err != nil {
@ -4325,6 +4335,7 @@ func autoConvert_v1_LifecycleHandler_To_core_LifecycleHandler(in *v1.LifecycleHa
out.Exec = (*core.ExecAction)(unsafe.Pointer(in.Exec))
out.HTTPGet = (*core.HTTPGetAction)(unsafe.Pointer(in.HTTPGet))
out.TCPSocket = (*core.TCPSocketAction)(unsafe.Pointer(in.TCPSocket))
out.Sleep = (*core.SleepAction)(unsafe.Pointer(in.Sleep))
return nil
}
@ -4337,6 +4348,7 @@ func autoConvert_core_LifecycleHandler_To_v1_LifecycleHandler(in *core.Lifecycle
out.Exec = (*v1.ExecAction)(unsafe.Pointer(in.Exec))
out.HTTPGet = (*v1.HTTPGetAction)(unsafe.Pointer(in.HTTPGet))
out.TCPSocket = (*v1.TCPSocketAction)(unsafe.Pointer(in.TCPSocket))
out.Sleep = (*v1.SleepAction)(unsafe.Pointer(in.Sleep))
return nil
}
@ -8067,6 +8079,26 @@ func Convert_core_SessionAffinityConfig_To_v1_SessionAffinityConfig(in *core.Ses
return autoConvert_core_SessionAffinityConfig_To_v1_SessionAffinityConfig(in, out, s)
}
func autoConvert_v1_SleepAction_To_core_SleepAction(in *v1.SleepAction, out *core.SleepAction, s conversion.Scope) error {
out.Seconds = in.Seconds
return nil
}
// Convert_v1_SleepAction_To_core_SleepAction is an autogenerated conversion function.
func Convert_v1_SleepAction_To_core_SleepAction(in *v1.SleepAction, out *core.SleepAction, s conversion.Scope) error {
return autoConvert_v1_SleepAction_To_core_SleepAction(in, out, s)
}
func autoConvert_core_SleepAction_To_v1_SleepAction(in *core.SleepAction, out *v1.SleepAction, s conversion.Scope) error {
out.Seconds = in.Seconds
return nil
}
// Convert_core_SleepAction_To_v1_SleepAction is an autogenerated conversion function.
func Convert_core_SleepAction_To_v1_SleepAction(in *core.SleepAction, out *v1.SleepAction, s conversion.Scope) error {
return autoConvert_core_SleepAction_To_v1_SleepAction(in, out, s)
}
func autoConvert_v1_StorageOSPersistentVolumeSource_To_core_StorageOSPersistentVolumeSource(in *v1.StorageOSPersistentVolumeSource, out *core.StorageOSPersistentVolumeSource, s conversion.Scope) error {
out.VolumeName = in.VolumeName
out.VolumeNamespace = in.VolumeNamespace

View File

@ -2886,52 +2886,52 @@ func validatePodResourceClaimSource(claimSource core.ClaimSource, fldPath *field
return allErrs
}
func validateLivenessProbe(probe *core.Probe, fldPath *field.Path) field.ErrorList {
func validateLivenessProbe(probe *core.Probe, gracePeriod int64, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if probe == nil {
return allErrs
}
allErrs = append(allErrs, validateProbe(probe, fldPath)...)
allErrs = append(allErrs, validateProbe(probe, gracePeriod, fldPath)...)
if probe.SuccessThreshold != 1 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("successThreshold"), probe.SuccessThreshold, "must be 1"))
}
return allErrs
}
func validateReadinessProbe(probe *core.Probe, fldPath *field.Path) field.ErrorList {
func validateReadinessProbe(probe *core.Probe, gracePeriod int64, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if probe == nil {
return allErrs
}
allErrs = append(allErrs, validateProbe(probe, fldPath)...)
allErrs = append(allErrs, validateProbe(probe, gracePeriod, fldPath)...)
if probe.TerminationGracePeriodSeconds != nil {
allErrs = append(allErrs, field.Invalid(fldPath.Child("terminationGracePeriodSeconds"), probe.TerminationGracePeriodSeconds, "must not be set for readinessProbes"))
}
return allErrs
}
func validateStartupProbe(probe *core.Probe, fldPath *field.Path) field.ErrorList {
func validateStartupProbe(probe *core.Probe, gracePeriod int64, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if probe == nil {
return allErrs
}
allErrs = append(allErrs, validateProbe(probe, fldPath)...)
allErrs = append(allErrs, validateProbe(probe, gracePeriod, fldPath)...)
if probe.SuccessThreshold != 1 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("successThreshold"), probe.SuccessThreshold, "must be 1"))
}
return allErrs
}
func validateProbe(probe *core.Probe, fldPath *field.Path) field.ErrorList {
func validateProbe(probe *core.Probe, gracePeriod int64, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if probe == nil {
return allErrs
}
allErrs = append(allErrs, validateHandler(handlerFromProbe(&probe.ProbeHandler), fldPath)...)
allErrs = append(allErrs, validateHandler(handlerFromProbe(&probe.ProbeHandler), gracePeriod, fldPath)...)
allErrs = append(allErrs, ValidateNonnegativeField(int64(probe.InitialDelaySeconds), fldPath.Child("initialDelaySeconds"))...)
allErrs = append(allErrs, ValidateNonnegativeField(int64(probe.TimeoutSeconds), fldPath.Child("timeoutSeconds"))...)
@ -2966,6 +2966,7 @@ type commonHandler struct {
HTTPGet *core.HTTPGetAction
TCPSocket *core.TCPSocketAction
GRPC *core.GRPCAction
Sleep *core.SleepAction
}
func handlerFromProbe(ph *core.ProbeHandler) commonHandler {
@ -2982,9 +2983,19 @@ func handlerFromLifecycle(lh *core.LifecycleHandler) commonHandler {
Exec: lh.Exec,
HTTPGet: lh.HTTPGet,
TCPSocket: lh.TCPSocket,
Sleep: lh.Sleep,
}
}
func validateSleepAction(sleep *core.SleepAction, gracePeriod int64, fldPath *field.Path) field.ErrorList {
allErrors := field.ErrorList{}
if sleep.Seconds <= 0 || sleep.Seconds > gracePeriod {
invalidStr := fmt.Sprintf("must be greater than 0 and less than terminationGracePeriodSeconds (%d)", gracePeriod)
allErrors = append(allErrors, field.Invalid(fldPath, sleep.Seconds, invalidStr))
}
return allErrors
}
func validateClientIPAffinityConfig(config *core.SessionAffinityConfig, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if config == nil {
@ -3093,7 +3104,7 @@ func validateTCPSocketAction(tcp *core.TCPSocketAction, fldPath *field.Path) fie
func validateGRPCAction(grpc *core.GRPCAction, fldPath *field.Path) field.ErrorList {
return ValidatePortNumOrName(intstr.FromInt32(grpc.Port), fldPath.Child("port"))
}
func validateHandler(handler commonHandler, fldPath *field.Path) field.ErrorList {
func validateHandler(handler commonHandler, gracePeriod int64, fldPath *field.Path) field.ErrorList {
numHandlers := 0
allErrors := field.ErrorList{}
if handler.Exec != nil {
@ -3128,19 +3139,27 @@ func validateHandler(handler commonHandler, fldPath *field.Path) field.ErrorList
allErrors = append(allErrors, validateGRPCAction(handler.GRPC, fldPath.Child("grpc"))...)
}
}
if handler.Sleep != nil {
if numHandlers > 0 {
allErrors = append(allErrors, field.Forbidden(fldPath.Child("sleep"), "may not specify more than 1 handler type"))
} else {
numHandlers++
allErrors = append(allErrors, validateSleepAction(handler.Sleep, gracePeriod, fldPath.Child("sleep"))...)
}
}
if numHandlers == 0 {
allErrors = append(allErrors, field.Required(fldPath, "must specify a handler type"))
}
return allErrors
}
func validateLifecycle(lifecycle *core.Lifecycle, fldPath *field.Path) field.ErrorList {
func validateLifecycle(lifecycle *core.Lifecycle, gracePeriod int64, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if lifecycle.PostStart != nil {
allErrs = append(allErrs, validateHandler(handlerFromLifecycle(lifecycle.PostStart), fldPath.Child("postStart"))...)
allErrs = append(allErrs, validateHandler(handlerFromLifecycle(lifecycle.PostStart), gracePeriod, fldPath.Child("postStart"))...)
}
if lifecycle.PreStop != nil {
allErrs = append(allErrs, validateHandler(handlerFromLifecycle(lifecycle.PreStop), fldPath.Child("preStop"))...)
allErrs = append(allErrs, validateHandler(handlerFromLifecycle(lifecycle.PreStop), gracePeriod, fldPath.Child("preStop"))...)
}
return allErrs
}
@ -3282,7 +3301,7 @@ func validateFieldAllowList(value interface{}, allowedFields map[string]bool, er
}
// validateInitContainers is called by pod spec and template validation to validate the list of init containers
func validateInitContainers(containers []core.Container, regularContainers []core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.String, fldPath *field.Path, opts PodValidationOptions, podRestartPolicy *core.RestartPolicy) field.ErrorList {
func validateInitContainers(containers []core.Container, regularContainers []core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.String, gracePeriod int64, fldPath *field.Path, opts PodValidationOptions, podRestartPolicy *core.RestartPolicy) field.ErrorList {
var allErrs field.ErrorList
allNames := sets.String{}
@ -3316,11 +3335,11 @@ func validateInitContainers(containers []core.Container, regularContainers []cor
switch {
case restartAlways:
if ctr.Lifecycle != nil {
allErrs = append(allErrs, validateLifecycle(ctr.Lifecycle, idxPath.Child("lifecycle"))...)
allErrs = append(allErrs, validateLifecycle(ctr.Lifecycle, gracePeriod, idxPath.Child("lifecycle"))...)
}
allErrs = append(allErrs, validateLivenessProbe(ctr.LivenessProbe, idxPath.Child("livenessProbe"))...)
allErrs = append(allErrs, validateReadinessProbe(ctr.ReadinessProbe, idxPath.Child("readinessProbe"))...)
allErrs = append(allErrs, validateStartupProbe(ctr.StartupProbe, idxPath.Child("startupProbe"))...)
allErrs = append(allErrs, validateLivenessProbe(ctr.LivenessProbe, gracePeriod, idxPath.Child("livenessProbe"))...)
allErrs = append(allErrs, validateReadinessProbe(ctr.ReadinessProbe, gracePeriod, idxPath.Child("readinessProbe"))...)
allErrs = append(allErrs, validateStartupProbe(ctr.StartupProbe, gracePeriod, idxPath.Child("startupProbe"))...)
default:
// These fields are disallowed for init containers.
@ -3420,7 +3439,7 @@ func validateHostUsers(spec *core.PodSpec, fldPath *field.Path) field.ErrorList
}
// validateContainers is called by pod spec and template validation to validate the list of regular containers.
func validateContainers(containers []core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.String, fldPath *field.Path, opts PodValidationOptions, podRestartPolicy *core.RestartPolicy) field.ErrorList {
func validateContainers(containers []core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.String, gracePeriod int64, fldPath *field.Path, opts PodValidationOptions, podRestartPolicy *core.RestartPolicy) field.ErrorList {
allErrs := field.ErrorList{}
if len(containers) == 0 {
@ -3448,11 +3467,11 @@ func validateContainers(containers []core.Container, volumes map[string]core.Vol
// Regular init container and ephemeral container validation will return
// field.Forbidden() for these paths.
if ctr.Lifecycle != nil {
allErrs = append(allErrs, validateLifecycle(ctr.Lifecycle, path.Child("lifecycle"))...)
allErrs = append(allErrs, validateLifecycle(ctr.Lifecycle, gracePeriod, path.Child("lifecycle"))...)
}
allErrs = append(allErrs, validateLivenessProbe(ctr.LivenessProbe, path.Child("livenessProbe"))...)
allErrs = append(allErrs, validateReadinessProbe(ctr.ReadinessProbe, path.Child("readinessProbe"))...)
allErrs = append(allErrs, validateStartupProbe(ctr.StartupProbe, path.Child("startupProbe"))...)
allErrs = append(allErrs, validateLivenessProbe(ctr.LivenessProbe, gracePeriod, path.Child("livenessProbe"))...)
allErrs = append(allErrs, validateReadinessProbe(ctr.ReadinessProbe, gracePeriod, path.Child("readinessProbe"))...)
allErrs = append(allErrs, validateStartupProbe(ctr.StartupProbe, gracePeriod, path.Child("startupProbe"))...)
// These fields are disallowed for regular containers
if ctr.RestartPolicy != nil {
@ -3974,12 +3993,18 @@ func validateHostIPs(pod *core.Pod) field.ErrorList {
func ValidatePodSpec(spec *core.PodSpec, podMeta *metav1.ObjectMeta, fldPath *field.Path, opts PodValidationOptions) field.ErrorList {
allErrs := field.ErrorList{}
var gracePeriod int64
if spec.TerminationGracePeriodSeconds != nil {
// this could happen in tests
gracePeriod = *spec.TerminationGracePeriodSeconds
}
vols, vErrs := ValidateVolumes(spec.Volumes, podMeta, fldPath.Child("volumes"), opts)
allErrs = append(allErrs, vErrs...)
podClaimNames := gatherPodResourceClaimNames(spec.ResourceClaims)
allErrs = append(allErrs, validatePodResourceClaims(podMeta, spec.ResourceClaims, fldPath.Child("resourceClaims"))...)
allErrs = append(allErrs, validateContainers(spec.Containers, vols, podClaimNames, fldPath.Child("containers"), opts, &spec.RestartPolicy)...)
allErrs = append(allErrs, validateInitContainers(spec.InitContainers, spec.Containers, vols, podClaimNames, fldPath.Child("initContainers"), opts, &spec.RestartPolicy)...)
allErrs = append(allErrs, validateContainers(spec.Containers, vols, podClaimNames, gracePeriod, fldPath.Child("containers"), opts, &spec.RestartPolicy)...)
allErrs = append(allErrs, validateInitContainers(spec.InitContainers, spec.Containers, vols, podClaimNames, gracePeriod, fldPath.Child("initContainers"), opts, &spec.RestartPolicy)...)
allErrs = append(allErrs, validateEphemeralContainers(spec.EphemeralContainers, spec.Containers, spec.InitContainers, vols, podClaimNames, fldPath.Child("ephemeralContainers"), opts, &spec.RestartPolicy)...)
allErrs = append(allErrs, validatePodHostNetworkDeps(spec, fldPath, opts)...)
allErrs = append(allErrs, validateRestartPolicy(&spec.RestartPolicy, fldPath.Child("restartPolicy"))...)

View File

@ -52,6 +52,7 @@ const (
dnsLabelErrMsg = "a lowercase RFC 1123 label must consist of"
dnsSubdomainLabelErrMsg = "a lowercase RFC 1123 subdomain"
envVarNameErrMsg = "a valid environment variable name must consist of"
defaultGracePeriod = int64(30)
)
var (
@ -6616,7 +6617,7 @@ func TestValidateProbe(t *testing.T) {
}
for _, p := range successCases {
if errs := validateProbe(p, field.NewPath("field")); len(errs) != 0 {
if errs := validateProbe(p, defaultGracePeriod, field.NewPath("field")); len(errs) != 0 {
t.Errorf("expected success: %v", errs)
}
}
@ -6628,7 +6629,7 @@ func TestValidateProbe(t *testing.T) {
errorCases = append(errorCases, probe)
}
for _, p := range errorCases {
if errs := validateProbe(p, field.NewPath("field")); len(errs) == 0 {
if errs := validateProbe(p, defaultGracePeriod, field.NewPath("field")); len(errs) == 0 {
t.Errorf("expected failure for %v", p)
}
}
@ -6734,7 +6735,7 @@ func Test_validateProbe(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := validateProbe(tt.args.probe, tt.args.fldPath)
got := validateProbe(tt.args.probe, defaultGracePeriod, tt.args.fldPath)
if len(got) != len(tt.want) {
t.Errorf("validateProbe() = %v, want %v", got, tt.want)
return
@ -6759,7 +6760,7 @@ func TestValidateHandler(t *testing.T) {
{HTTPGet: &core.HTTPGetAction{Path: "/", Port: intstr.FromString("port"), Host: "", Scheme: "HTTP", HTTPHeaders: []core.HTTPHeader{{Name: "X-Forwarded-For", Value: "1.2.3.4"}, {Name: "X-Forwarded-For", Value: "5.6.7.8"}}}},
}
for _, h := range successCases {
if errs := validateHandler(handlerFromProbe(&h), field.NewPath("field")); len(errs) != 0 {
if errs := validateHandler(handlerFromProbe(&h), defaultGracePeriod, field.NewPath("field")); len(errs) != 0 {
t.Errorf("expected success: %v", errs)
}
}
@ -6774,7 +6775,7 @@ func TestValidateHandler(t *testing.T) {
{HTTPGet: &core.HTTPGetAction{Path: "/", Port: intstr.FromString("port"), Host: "", Scheme: "HTTP", HTTPHeaders: []core.HTTPHeader{{Name: "X_Forwarded_For", Value: "foo.example.com"}}}},
}
for _, h := range errorCases {
if errs := validateHandler(handlerFromProbe(&h), field.NewPath("field")); len(errs) == 0 {
if errs := validateHandler(handlerFromProbe(&h), defaultGracePeriod, field.NewPath("field")); len(errs) == 0 {
t.Errorf("expected failure for %#v", h)
}
}
@ -7694,7 +7695,7 @@ func TestValidateContainers(t *testing.T) {
var PodRestartPolicy core.RestartPolicy
PodRestartPolicy = "Always"
if errs := validateContainers(successCase, volumeDevices, nil, field.NewPath("field"), PodValidationOptions{}, &PodRestartPolicy); len(errs) != 0 {
if errs := validateContainers(successCase, volumeDevices, nil, defaultGracePeriod, field.NewPath("field"), PodValidationOptions{}, &PodRestartPolicy); len(errs) != 0 {
t.Errorf("expected success: %v", errs)
}
@ -8308,7 +8309,7 @@ func TestValidateContainers(t *testing.T) {
for _, tc := range errorCases {
t.Run(tc.title+"__@L"+tc.line, func(t *testing.T) {
errs := validateContainers(tc.containers, volumeDevices, nil, field.NewPath("containers"), PodValidationOptions{}, &PodRestartPolicy)
errs := validateContainers(tc.containers, volumeDevices, nil, defaultGracePeriod, field.NewPath("containers"), PodValidationOptions{}, &PodRestartPolicy)
if len(errs) == 0 {
t.Fatal("expected error but received none")
}
@ -8398,7 +8399,7 @@ func TestValidateInitContainers(t *testing.T) {
}
var PodRestartPolicy core.RestartPolicy
PodRestartPolicy = "Never"
if errs := validateInitContainers(successCase, containers, volumeDevices, nil, field.NewPath("field"), PodValidationOptions{}, &PodRestartPolicy); len(errs) != 0 {
if errs := validateInitContainers(successCase, containers, volumeDevices, nil, defaultGracePeriod, field.NewPath("field"), PodValidationOptions{}, &PodRestartPolicy); len(errs) != 0 {
t.Errorf("expected success: %v", errs)
}
@ -8777,7 +8778,7 @@ func TestValidateInitContainers(t *testing.T) {
for _, tc := range errorCases {
t.Run(tc.title+"__@L"+tc.line, func(t *testing.T) {
errs := validateInitContainers(tc.initContainers, containers, volumeDevices, nil, field.NewPath("initContainers"), PodValidationOptions{}, &PodRestartPolicy)
errs := validateInitContainers(tc.initContainers, containers, volumeDevices, nil, defaultGracePeriod, field.NewPath("initContainers"), PodValidationOptions{}, &PodRestartPolicy)
if len(errs) == 0 {
t.Fatal("expected error but received none")
}
@ -23702,3 +23703,57 @@ func TestValidateLoadBalancerStatus(t *testing.T) {
})
}
}
func TestValidateSleepAction(t *testing.T) {
fldPath := field.NewPath("root")
getInvalidStr := func(gracePeriod int64) string {
return fmt.Sprintf("must be greater than 0 and less than terminationGracePeriodSeconds (%d)", gracePeriod)
}
testCases := []struct {
name string
action *core.SleepAction
gracePeriod int64
expectErr field.ErrorList
}{
{
name: "valid setting",
action: &core.SleepAction{
Seconds: 5,
},
gracePeriod: 30,
},
{
name: "negative seconds",
action: &core.SleepAction{
Seconds: -1,
},
gracePeriod: 30,
expectErr: field.ErrorList{field.Invalid(fldPath, -1, getInvalidStr(30))},
},
{
name: "longer than gracePeriod",
action: &core.SleepAction{
Seconds: 5,
},
gracePeriod: 3,
expectErr: field.ErrorList{field.Invalid(fldPath, 5, getInvalidStr(3))},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
errs := validateSleepAction(tc.action, tc.gracePeriod, fldPath)
if len(tc.expectErr) > 0 && len(errs) == 0 {
t.Errorf("Unexpected success")
} else if len(tc.expectErr) == 0 && len(errs) != 0 {
t.Errorf("Unexpected error(s): %v", errs)
} else if len(tc.expectErr) > 0 {
if tc.expectErr[0].Error() != errs[0].Error() {
t.Errorf("Unexpected error(s): %v", errs)
}
}
})
}
}

View File

@ -2045,6 +2045,11 @@ func (in *LifecycleHandler) DeepCopyInto(out *LifecycleHandler) {
*out = new(TCPSocketAction)
**out = **in
}
if in.Sleep != nil {
in, out := &in.Sleep, &out.Sleep
*out = new(SleepAction)
**out = **in
}
return
}
@ -5671,6 +5676,22 @@ func (in *SessionAffinityConfig) DeepCopy() *SessionAffinityConfig {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *SleepAction) DeepCopyInto(out *SleepAction) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SleepAction.
func (in *SleepAction) DeepCopy() *SleepAction {
if in == nil {
return nil
}
out := new(SleepAction)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *StorageOSPersistentVolumeSource) DeepCopyInto(out *StorageOSPersistentVolumeSource) {
*out = *in

View File

@ -636,6 +636,13 @@ const (
// Adds pod.status.hostIPs and downward API
PodHostIPs featuregate.Feature = "PodHostIPs"
// owner: @AxeZhan
// kep: http://kep.k8s.io/3960
// alpha: v1.29
//
// Enables SleepAction in container lifecycle hooks
PodLifecycleSleepAction featuregate.Feature = "PodLifecycleSleepAction"
// owner: @Huang-Wei
// kep: https://kep.k8s.io/3521
// alpha: v1.26
@ -1063,6 +1070,8 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
PodHostIPs: {Default: false, PreRelease: featuregate.Alpha},
PodLifecycleSleepAction: {Default: false, PreRelease: featuregate.Alpha},
PodSchedulingReadiness: {Default: true, PreRelease: featuregate.Beta},
ProbeTerminationGracePeriod: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.29

View File

@ -552,6 +552,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"k8s.io/api/core/v1.ServiceSpec": schema_k8sio_api_core_v1_ServiceSpec(ref),
"k8s.io/api/core/v1.ServiceStatus": schema_k8sio_api_core_v1_ServiceStatus(ref),
"k8s.io/api/core/v1.SessionAffinityConfig": schema_k8sio_api_core_v1_SessionAffinityConfig(ref),
"k8s.io/api/core/v1.SleepAction": schema_k8sio_api_core_v1_SleepAction(ref),
"k8s.io/api/core/v1.StorageOSPersistentVolumeSource": schema_k8sio_api_core_v1_StorageOSPersistentVolumeSource(ref),
"k8s.io/api/core/v1.StorageOSVolumeSource": schema_k8sio_api_core_v1_StorageOSVolumeSource(ref),
"k8s.io/api/core/v1.Sysctl": schema_k8sio_api_core_v1_Sysctl(ref),
@ -21408,11 +21409,17 @@ func schema_k8sio_api_core_v1_LifecycleHandler(ref common.ReferenceCallback) com
Ref: ref("k8s.io/api/core/v1.TCPSocketAction"),
},
},
"sleep": {
SchemaProps: spec.SchemaProps{
Description: "Sleep represents the duration that the container should sleep before being terminated.",
Ref: ref("k8s.io/api/core/v1.SleepAction"),
},
},
},
},
},
Dependencies: []string{
"k8s.io/api/core/v1.ExecAction", "k8s.io/api/core/v1.HTTPGetAction", "k8s.io/api/core/v1.TCPSocketAction"},
"k8s.io/api/core/v1.ExecAction", "k8s.io/api/core/v1.HTTPGetAction", "k8s.io/api/core/v1.SleepAction", "k8s.io/api/core/v1.TCPSocketAction"},
}
}
@ -28387,6 +28394,28 @@ func schema_k8sio_api_core_v1_SessionAffinityConfig(ref common.ReferenceCallback
}
}
func schema_k8sio_api_core_v1_SleepAction(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "SleepAction describes a \"sleep\" action.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"seconds": {
SchemaProps: spec.SchemaProps{
Description: "Seconds is the number of seconds to sleep.",
Default: 0,
Type: []string{"integer"},
Format: "int64",
},
},
},
Required: []string{"seconds"},
},
},
}
}
func schema_k8sio_api_core_v1_StorageOSPersistentVolumeSource(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{

View File

@ -26,6 +26,7 @@ import (
"net/url"
"strconv"
"strings"
"time"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
@ -86,6 +87,14 @@ func (hr *handlerRunner) Run(ctx context.Context, containerID kubecontainer.Cont
klog.V(1).ErrorS(err, "HTTP lifecycle hook for Container in Pod failed", "path", handler.HTTPGet.Path, "containerName", container.Name, "pod", klog.KObj(pod))
}
return msg, err
case handler.Sleep != nil:
err := hr.runSleepHandler(ctx, handler.Sleep.Seconds)
var msg string
if err != nil {
msg = fmt.Sprintf("Sleep lifecycle hook (%d) for Container %q in Pod %q failed - error: %v", handler.Sleep.Seconds, container.Name, format.Pod(pod), err)
klog.V(1).ErrorS(err, "Sleep lifecycle hook for Container in Pod failed", "sleepSeconds", handler.Sleep.Seconds, "containerName", container.Name, "pod", klog.KObj(pod))
}
return msg, err
default:
err := fmt.Errorf("invalid handler: %v", handler)
msg := fmt.Sprintf("Cannot run handler: %v", err)
@ -117,6 +126,20 @@ func resolvePort(portReference intstr.IntOrString, container *v1.Container) (int
return -1, fmt.Errorf("couldn't find port: %v in %v", portReference, container)
}
func (hr *handlerRunner) runSleepHandler(ctx context.Context, seconds int64) error {
if !utilfeature.DefaultFeatureGate.Enabled(features.PodLifecycleSleepAction) {
return nil
}
c := time.After(time.Duration(seconds) * time.Second)
select {
case <-ctx.Done():
// unexpected termination
return fmt.Errorf("container terminated before sleep hook finished")
case <-c:
return nil
}
}
func (hr *handlerRunner) runHTTPHandler(ctx context.Context, pod *v1.Pod, container *v1.Container, handler *v1.LifecycleHandler, eventRecorder record.EventRecorder) error {
host := handler.HTTPGet.Host
podIP := host

View File

@ -859,3 +859,59 @@ func TestIsHTTPResponseError(t *testing.T) {
t.Errorf("unexpected http response error: %v", err)
}
}
func TestRunSleepHandler(t *testing.T) {
handlerRunner := NewHandlerRunner(&fakeHTTP{}, &fakeContainerCommandRunner{}, nil, nil)
containerID := kubecontainer.ContainerID{Type: "test", ID: "abc1234"}
containerName := "containerFoo"
container := v1.Container{
Name: containerName,
Lifecycle: &v1.Lifecycle{
PreStop: &v1.LifecycleHandler{},
},
}
pod := v1.Pod{}
pod.ObjectMeta.Name = "podFoo"
pod.ObjectMeta.Namespace = "nsFoo"
pod.Spec.Containers = []v1.Container{container}
tests := []struct {
name string
sleepSeconds int64
terminationGracePeriodSeconds int64
expectErr bool
expectedErr string
}{
{
name: "valid seconds",
sleepSeconds: 5,
terminationGracePeriodSeconds: 30,
},
{
name: "longer than TerminationGracePeriodSeconds",
sleepSeconds: 3,
terminationGracePeriodSeconds: 2,
expectErr: true,
expectedErr: "container terminated before sleep hook finished",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodLifecycleSleepAction, true)()
pod.Spec.Containers[0].Lifecycle.PreStop.Sleep = &v1.SleepAction{Seconds: tt.sleepSeconds}
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(tt.terminationGracePeriodSeconds)*time.Second)
defer cancel()
_, err := handlerRunner.Run(ctx, containerID, &pod, &container, container.Lifecycle.PreStop)
if !tt.expectErr && err != nil {
t.Errorf("unexpected success")
}
if tt.expectErr && err.Error() != tt.expectedErr {
t.Errorf("%s: expected error want %s, got %s", tt.name, tt.expectedErr, err.Error())
}
})
}
}

File diff suppressed because it is too large Load Diff

View File

@ -2088,6 +2088,11 @@ message LifecycleHandler {
// lifecycle hooks will fail in runtime when tcp handler is specified.
// +optional
optional TCPSocketAction tcpSocket = 3;
// Sleep represents the duration that the container should sleep before being terminated.
// +featureGate=PodLifecycleSleepAction
// +optional
optional SleepAction sleep = 4;
}
// LimitRange sets resource usage limits for each kind of resource in a Namespace.
@ -5562,6 +5567,12 @@ message SessionAffinityConfig {
optional ClientIPConfig clientIP = 1;
}
// SleepAction describes a "sleep" action.
message SleepAction {
// Seconds is the number of seconds to sleep.
optional int64 seconds = 1;
}
// Represents a StorageOS persistent volume resource.
message StorageOSPersistentVolumeSource {
// volumeName is the human-readable name of the StorageOS volume. Volume

View File

@ -2272,6 +2272,12 @@ type ExecAction struct {
Command []string `json:"command,omitempty" protobuf:"bytes,1,rep,name=command"`
}
// SleepAction describes a "sleep" action.
type SleepAction struct {
// Seconds is the number of seconds to sleep.
Seconds int64 `json:"seconds" protobuf:"bytes,1,opt,name=seconds"`
}
// Probe describes a health check to be performed against a container to determine whether it is
// alive or ready to receive traffic.
type Probe struct {
@ -2667,6 +2673,10 @@ type LifecycleHandler struct {
// lifecycle hooks will fail in runtime when tcp handler is specified.
// +optional
TCPSocket *TCPSocketAction `json:"tcpSocket,omitempty" protobuf:"bytes,3,opt,name=tcpSocket"`
// Sleep represents the duration that the container should sleep before being terminated.
// +featureGate=PodLifecycleSleepAction
// +optional
Sleep *SleepAction `json:"sleep,omitempty" protobuf:"bytes,4,opt,name=sleep"`
}
// Lifecycle describes actions that the management system should take in response to container lifecycle

View File

@ -935,6 +935,7 @@ var map_LifecycleHandler = map[string]string{
"exec": "Exec specifies the action to take.",
"httpGet": "HTTPGet specifies the http request to perform.",
"tcpSocket": "Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept for the backward compatibility. There are no validation of this field and lifecycle hooks will fail in runtime when tcp handler is specified.",
"sleep": "Sleep represents the duration that the container should sleep before being terminated.",
}
func (LifecycleHandler) SwaggerDoc() map[string]string {
@ -2391,6 +2392,15 @@ func (SessionAffinityConfig) SwaggerDoc() map[string]string {
return map_SessionAffinityConfig
}
var map_SleepAction = map[string]string{
"": "SleepAction describes a \"sleep\" action.",
"seconds": "Seconds is the number of seconds to sleep.",
}
func (SleepAction) SwaggerDoc() map[string]string {
return map_SleepAction
}
var map_StorageOSPersistentVolumeSource = map[string]string{
"": "Represents a StorageOS persistent volume resource.",
"volumeName": "volumeName is the human-readable name of the StorageOS volume. Volume names are only unique within a namespace.",

View File

@ -2045,6 +2045,11 @@ func (in *LifecycleHandler) DeepCopyInto(out *LifecycleHandler) {
*out = new(TCPSocketAction)
**out = **in
}
if in.Sleep != nil {
in, out := &in.Sleep, &out.Sleep
*out = new(SleepAction)
**out = **in
}
return
}
@ -5686,6 +5691,22 @@ func (in *SessionAffinityConfig) DeepCopy() *SessionAffinityConfig {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *SleepAction) DeepCopyInto(out *SleepAction) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SleepAction.
func (in *SleepAction) DeepCopy() *SleepAction {
if in == nil {
return nil
}
out := new(SleepAction)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *StorageOSPersistentVolumeSource) DeepCopyInto(out *StorageOSPersistentVolumeSource) {
*out = *in

View File

@ -690,6 +690,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -713,6 +716,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -974,6 +980,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -997,6 +1006,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -1258,6 +1270,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -1281,6 +1296,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},

View File

@ -239,6 +239,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -254,6 +256,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -446,6 +450,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -461,6 +467,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -655,6 +663,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -670,6 +680,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue

View File

@ -691,6 +691,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -714,6 +717,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -975,6 +981,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -998,6 +1007,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -1259,6 +1271,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -1282,6 +1297,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},

View File

@ -247,6 +247,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -262,6 +264,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -454,6 +458,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -469,6 +475,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -663,6 +671,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -678,6 +688,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue

View File

@ -692,6 +692,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -715,6 +718,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -976,6 +982,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -999,6 +1008,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -1260,6 +1272,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -1283,6 +1298,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},

View File

@ -239,6 +239,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -254,6 +256,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -446,6 +450,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -461,6 +467,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -655,6 +663,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -670,6 +680,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue

View File

@ -691,6 +691,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -714,6 +717,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -975,6 +981,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -998,6 +1007,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -1259,6 +1271,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -1282,6 +1297,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},

View File

@ -247,6 +247,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -262,6 +264,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -454,6 +458,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -469,6 +475,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -663,6 +671,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -678,6 +688,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue

View File

@ -691,6 +691,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -714,6 +717,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -975,6 +981,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -998,6 +1007,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -1259,6 +1271,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -1282,6 +1297,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},

View File

@ -249,6 +249,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -264,6 +266,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -456,6 +460,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -471,6 +477,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -665,6 +673,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -680,6 +690,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue

View File

@ -691,6 +691,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -714,6 +717,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -975,6 +981,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -998,6 +1007,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -1259,6 +1271,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -1282,6 +1297,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},

View File

@ -247,6 +247,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -262,6 +264,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -454,6 +458,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -469,6 +475,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -663,6 +671,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -678,6 +688,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue

View File

@ -690,6 +690,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -713,6 +716,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -974,6 +980,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -997,6 +1006,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -1258,6 +1270,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -1281,6 +1296,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},

View File

@ -239,6 +239,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -254,6 +256,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -446,6 +450,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -461,6 +467,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -655,6 +663,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -670,6 +680,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue

View File

@ -691,6 +691,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -714,6 +717,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -975,6 +981,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -998,6 +1007,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -1259,6 +1271,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -1282,6 +1297,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},

View File

@ -247,6 +247,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -262,6 +264,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -454,6 +458,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -469,6 +475,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -663,6 +671,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -678,6 +688,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue

View File

@ -692,6 +692,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -715,6 +718,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -976,6 +982,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -999,6 +1008,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -1260,6 +1272,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -1283,6 +1298,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},

View File

@ -239,6 +239,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -254,6 +256,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -446,6 +450,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -461,6 +467,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -655,6 +663,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -670,6 +680,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue

View File

@ -691,6 +691,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -714,6 +717,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -975,6 +981,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -998,6 +1007,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -1259,6 +1271,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -1282,6 +1297,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},

View File

@ -247,6 +247,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -262,6 +264,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -454,6 +458,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -469,6 +475,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -663,6 +671,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -678,6 +688,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue

View File

@ -766,6 +766,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -789,6 +792,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -1050,6 +1056,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -1073,6 +1082,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -1334,6 +1346,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -1357,6 +1372,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},

View File

@ -294,6 +294,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -309,6 +311,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -501,6 +505,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -516,6 +522,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -710,6 +718,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -725,6 +735,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue

View File

@ -717,6 +717,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -740,6 +743,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -1001,6 +1007,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -1024,6 +1033,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -1285,6 +1297,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -1308,6 +1323,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},

View File

@ -258,6 +258,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -273,6 +275,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -465,6 +469,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -480,6 +486,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -674,6 +682,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -689,6 +699,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue

View File

@ -766,6 +766,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -789,6 +792,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -1050,6 +1056,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -1073,6 +1082,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -1334,6 +1346,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -1357,6 +1372,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},

View File

@ -294,6 +294,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -309,6 +311,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -501,6 +505,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -516,6 +522,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -710,6 +718,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -725,6 +735,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue

View File

@ -632,6 +632,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -655,6 +658,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -916,6 +922,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -939,6 +948,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -1200,6 +1212,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -1223,6 +1238,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},

View File

@ -195,6 +195,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -210,6 +212,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -402,6 +406,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -417,6 +423,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -611,6 +619,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -626,6 +636,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue

View File

@ -675,6 +675,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -698,6 +701,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -959,6 +965,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -982,6 +991,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -1243,6 +1255,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -1266,6 +1281,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},

View File

@ -228,6 +228,8 @@ template:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -243,6 +245,8 @@ template:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -435,6 +439,8 @@ template:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -450,6 +456,8 @@ template:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -644,6 +652,8 @@ template:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -659,6 +669,8 @@ template:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue

View File

@ -681,6 +681,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -704,6 +707,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -965,6 +971,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -988,6 +997,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -1249,6 +1261,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -1272,6 +1287,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},

View File

@ -233,6 +233,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -248,6 +250,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -440,6 +444,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -455,6 +461,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -649,6 +657,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -664,6 +674,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue

View File

@ -690,6 +690,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -713,6 +716,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -974,6 +980,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -997,6 +1006,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -1258,6 +1270,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -1281,6 +1296,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},

View File

@ -239,6 +239,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -254,6 +256,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -446,6 +450,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -461,6 +467,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -655,6 +663,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -670,6 +680,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue

View File

@ -691,6 +691,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -714,6 +717,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -975,6 +981,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -998,6 +1007,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -1259,6 +1271,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -1282,6 +1297,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},

View File

@ -249,6 +249,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -264,6 +266,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -456,6 +460,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -471,6 +477,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -665,6 +673,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -680,6 +690,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue

View File

@ -692,6 +692,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -715,6 +718,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -976,6 +982,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -999,6 +1008,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},
@ -1260,6 +1272,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
},
"preStop": {
@ -1283,6 +1298,9 @@
"tcpSocket": {
"port": "portValue",
"host": "hostValue"
},
"sleep": {
"seconds": 1
}
}
},

View File

@ -239,6 +239,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -254,6 +256,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -446,6 +450,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -461,6 +467,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -655,6 +663,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue
@ -670,6 +680,8 @@ spec:
path: pathValue
port: portValue
scheme: schemeValue
sleep:
seconds: 1
tcpSocket:
host: hostValue
port: portValue

View File

@ -24,6 +24,7 @@ type LifecycleHandlerApplyConfiguration struct {
Exec *ExecActionApplyConfiguration `json:"exec,omitempty"`
HTTPGet *HTTPGetActionApplyConfiguration `json:"httpGet,omitempty"`
TCPSocket *TCPSocketActionApplyConfiguration `json:"tcpSocket,omitempty"`
Sleep *SleepActionApplyConfiguration `json:"sleep,omitempty"`
}
// LifecycleHandlerApplyConfiguration constructs an declarative configuration of the LifecycleHandler type for use with
@ -55,3 +56,11 @@ func (b *LifecycleHandlerApplyConfiguration) WithTCPSocket(value *TCPSocketActio
b.TCPSocket = value
return b
}
// WithSleep sets the Sleep field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Sleep field is set to the value of the last call.
func (b *LifecycleHandlerApplyConfiguration) WithSleep(value *SleepActionApplyConfiguration) *LifecycleHandlerApplyConfiguration {
b.Sleep = value
return b
}

View File

@ -0,0 +1,39 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by applyconfiguration-gen. DO NOT EDIT.
package v1
// SleepActionApplyConfiguration represents an declarative configuration of the SleepAction type for use
// with apply.
type SleepActionApplyConfiguration struct {
Seconds *int64 `json:"seconds,omitempty"`
}
// SleepActionApplyConfiguration constructs an declarative configuration of the SleepAction type for use with
// apply.
func SleepAction() *SleepActionApplyConfiguration {
return &SleepActionApplyConfiguration{}
}
// WithSeconds sets the Seconds field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Seconds field is set to the value of the last call.
func (b *SleepActionApplyConfiguration) WithSeconds(value int64) *SleepActionApplyConfiguration {
b.Seconds = &value
return b
}

View File

@ -5497,6 +5497,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: httpGet
type:
namedType: io.k8s.api.core.v1.HTTPGetAction
- name: sleep
type:
namedType: io.k8s.api.core.v1.SleepAction
- name: tcpSocket
type:
namedType: io.k8s.api.core.v1.TCPSocketAction
@ -7565,6 +7568,13 @@ var schemaYAML = typed.YAMLObject(`types:
- name: clientIP
type:
namedType: io.k8s.api.core.v1.ClientIPConfig
- name: io.k8s.api.core.v1.SleepAction
map:
fields:
- name: seconds
type:
scalar: numeric
default: 0
- name: io.k8s.api.core.v1.StorageOSPersistentVolumeSource
map:
fields:

View File

@ -911,6 +911,8 @@ func ForKind(kind schema.GroupVersionKind) interface{} {
return &applyconfigurationscorev1.ServiceStatusApplyConfiguration{}
case corev1.SchemeGroupVersion.WithKind("SessionAffinityConfig"):
return &applyconfigurationscorev1.SessionAffinityConfigApplyConfiguration{}
case corev1.SchemeGroupVersion.WithKind("SleepAction"):
return &applyconfigurationscorev1.SleepActionApplyConfiguration{}
case corev1.SchemeGroupVersion.WithKind("StorageOSPersistentVolumeSource"):
return &applyconfigurationscorev1.StorageOSPersistentVolumeSourceApplyConfiguration{}
case corev1.SchemeGroupVersion.WithKind("StorageOSVolumeSource"):

View File

@ -544,3 +544,52 @@ func getSidecarPodWithHook(name string, image string, lifecycle *v1.Lifecycle) *
},
}
}
var _ = SIGDescribe("[Feature:PodLifecycleSleepAction]", func() {
f := framework.NewDefaultFramework("pod-lifecycle-sleep-action")
f.NamespacePodSecurityEnforceLevel = admissionapi.LevelBaseline
var podClient *e2epod.PodClient
ginkgo.Context("when create a pod with lifecycle hook using sleep action", func() {
ginkgo.BeforeEach(func(ctx context.Context) {
podClient = e2epod.NewPodClient(f)
})
ginkgo.It("valid prestop hook using sleep action", func(ctx context.Context) {
lifecycle := &v1.Lifecycle{
PreStop: &v1.LifecycleHandler{
Sleep: &v1.SleepAction{Seconds: 5},
},
}
podWithHook := getPodWithHook("pod-with-prestop-sleep-hook", imageutils.GetPauseImageName(), lifecycle)
ginkgo.By("create the pod with lifecycle hook using sleep action")
podClient.CreateSync(ctx, podWithHook)
ginkgo.By("delete the pod with lifecycle hook using sleep action")
start := time.Now()
podClient.DeleteSync(ctx, podWithHook.Name, metav1.DeleteOptions{}, e2epod.DefaultPodDeletionTimeout)
cost := time.Since(start)
// verify that deletion was delayed by sleep seconds
if cost < time.Second*5 || cost > time.Second*10 {
framework.Failf("unexpected delay duration before killing the pod")
}
})
ginkgo.It("reduce GracePeriodSeconds during runtime", func(ctx context.Context) {
lifecycle := &v1.Lifecycle{
PreStop: &v1.LifecycleHandler{
Sleep: &v1.SleepAction{Seconds: 10},
},
}
podWithHook := getPodWithHook("pod-with-prestop-sleep-hook", imageutils.GetPauseImageName(), lifecycle)
ginkgo.By("create the pod with lifecycle hook using sleep action")
podClient.CreateSync(ctx, podWithHook)
ginkgo.By("delete the pod with lifecycle hook using sleep action")
start := time.Now()
podClient.DeleteSync(ctx, podWithHook.Name, *metav1.NewDeleteOptions(2), e2epod.DefaultPodDeletionTimeout)
cost := time.Since(start)
// verify that deletion was delayed by sleep seconds
if cost <= time.Second || cost >= time.Second*5 {
framework.Failf("unexpected delay duration before killing the pod")
}
})
})
})