Skip to content

Commit ff25881

Browse files
authored
Merge pull request kubernetes#130556 from sreeram-venkitesh/kep-4960-container-stop-signals
KEP 4960: Container Stop Signals
2 parents 34e80be + 52c3010 commit ff25881

File tree

93 files changed

+2977
-1572
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+2977
-1572
lines changed

api/openapi-spec/swagger.json

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/openapi-spec/v3/api__v1_openapi.json

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/openapi-spec/v3/apis__apps__v1_openapi.json

+4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/openapi-spec/v3/apis__batch__v1_openapi.json

+4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/api/pod/testing/make.go

+6
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,12 @@ func SetContainerImage(image string) TweakContainer {
270270
}
271271
}
272272

273+
func SetContainerLifecycle(lifecycle api.Lifecycle) TweakContainer {
274+
return func(cnr *api.Container) {
275+
cnr.Lifecycle = &lifecycle
276+
}
277+
}
278+
273279
func MakeResourceRequirements(requests, limits map[string]string) api.ResourceRequirements {
274280
rr := api.ResourceRequirements{Requests: api.ResourceList{}, Limits: api.ResourceList{}}
275281
for k, v := range requests {

pkg/api/pod/util.go

+48-3
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,51 @@ func dropDisabledFields(
678678
dropPodLifecycleSleepAction(podSpec, oldPodSpec)
679679
dropImageVolumes(podSpec, oldPodSpec)
680680
dropSELinuxChangePolicy(podSpec, oldPodSpec)
681+
dropContainerStopSignals(podSpec, oldPodSpec)
682+
}
683+
684+
func dropContainerStopSignals(podSpec, oldPodSpec *api.PodSpec) {
685+
if utilfeature.DefaultFeatureGate.Enabled(features.ContainerStopSignals) || containerStopSignalsInUse(oldPodSpec) {
686+
return
687+
}
688+
689+
wipeLifecycle := func(ctr *api.Container) {
690+
if ctr.Lifecycle == nil {
691+
return
692+
}
693+
if ctr.Lifecycle.StopSignal != nil {
694+
ctr.Lifecycle.StopSignal = nil
695+
if *ctr.Lifecycle == (api.Lifecycle{}) {
696+
ctr.Lifecycle = nil
697+
}
698+
}
699+
}
700+
701+
VisitContainers(podSpec, AllContainers, func(c *api.Container, containerType ContainerType) bool {
702+
if c.Lifecycle == nil {
703+
return true
704+
}
705+
wipeLifecycle(c)
706+
return true
707+
})
708+
}
709+
710+
func containerStopSignalsInUse(podSpec *api.PodSpec) bool {
711+
if podSpec == nil {
712+
return false
713+
}
714+
var inUse bool
715+
VisitContainers(podSpec, AllContainers, func(c *api.Container, containerType ContainerType) bool {
716+
if c.Lifecycle == nil {
717+
return true
718+
}
719+
if c.Lifecycle.StopSignal != nil {
720+
inUse = true
721+
return false
722+
}
723+
return true
724+
})
725+
return inUse
681726
}
682727

683728
func dropDisabledPodLevelResources(podSpec, oldPodSpec *api.PodSpec) {
@@ -713,7 +758,7 @@ func dropPodLifecycleSleepAction(podSpec, oldPodSpec *api.PodSpec) {
713758
continue
714759
}
715760
adjustLifecycle(podSpec.Containers[i].Lifecycle)
716-
if podSpec.Containers[i].Lifecycle.PreStop == nil && podSpec.Containers[i].Lifecycle.PostStart == nil {
761+
if podSpec.Containers[i].Lifecycle.PreStop == nil && podSpec.Containers[i].Lifecycle.PostStart == nil && podSpec.Containers[i].Lifecycle.StopSignal == nil {
717762
podSpec.Containers[i].Lifecycle = nil
718763
}
719764
}
@@ -723,7 +768,7 @@ func dropPodLifecycleSleepAction(podSpec, oldPodSpec *api.PodSpec) {
723768
continue
724769
}
725770
adjustLifecycle(podSpec.InitContainers[i].Lifecycle)
726-
if podSpec.InitContainers[i].Lifecycle.PreStop == nil && podSpec.InitContainers[i].Lifecycle.PostStart == nil {
771+
if podSpec.InitContainers[i].Lifecycle.PreStop == nil && podSpec.InitContainers[i].Lifecycle.PostStart == nil && podSpec.InitContainers[i].Lifecycle.StopSignal == nil {
727772
podSpec.InitContainers[i].Lifecycle = nil
728773
}
729774
}
@@ -733,7 +778,7 @@ func dropPodLifecycleSleepAction(podSpec, oldPodSpec *api.PodSpec) {
733778
continue
734779
}
735780
adjustLifecycle(podSpec.EphemeralContainers[i].Lifecycle)
736-
if podSpec.EphemeralContainers[i].Lifecycle.PreStop == nil && podSpec.EphemeralContainers[i].Lifecycle.PostStart == nil {
781+
if podSpec.EphemeralContainers[i].Lifecycle.PreStop == nil && podSpec.EphemeralContainers[i].Lifecycle.PostStart == nil && podSpec.EphemeralContainers[i].Lifecycle.StopSignal == nil {
737782
podSpec.EphemeralContainers[i].Lifecycle = nil
738783
}
739784
}

pkg/api/pod/util_test.go

+142
Original file line numberDiff line numberDiff line change
@@ -3436,6 +3436,148 @@ func TestDropPodLifecycleSleepAction(t *testing.T) {
34363436
}
34373437
}
34383438

3439+
func TestDropContainerStopSignals(t *testing.T) {
3440+
makeContainer := func(lifecycle *api.Lifecycle) api.Container {
3441+
container := api.Container{Name: "foo"}
3442+
if lifecycle != nil {
3443+
container.Lifecycle = lifecycle
3444+
}
3445+
return container
3446+
}
3447+
3448+
makeEphemeralContainer := func(lifecycle *api.Lifecycle) api.EphemeralContainer {
3449+
container := api.EphemeralContainer{
3450+
EphemeralContainerCommon: api.EphemeralContainerCommon{Name: "foo"},
3451+
}
3452+
if lifecycle != nil {
3453+
container.Lifecycle = lifecycle
3454+
}
3455+
return container
3456+
}
3457+
3458+
makePod := func(os api.OSName, containers []api.Container, initContainers []api.Container, ephemeralContainers []api.EphemeralContainer) *api.PodSpec {
3459+
return &api.PodSpec{
3460+
OS: &api.PodOS{Name: os},
3461+
Containers: containers,
3462+
InitContainers: initContainers,
3463+
EphemeralContainers: ephemeralContainers,
3464+
}
3465+
}
3466+
3467+
testCases := []struct {
3468+
featuregateEnabled bool
3469+
oldLifecycle *api.Lifecycle
3470+
newLifecycle *api.Lifecycle
3471+
expectedLifecycle *api.Lifecycle
3472+
}{
3473+
// feature gate is turned on and stopsignal is not in use - Lifecycle stays nil
3474+
{
3475+
featuregateEnabled: true,
3476+
oldLifecycle: nil,
3477+
newLifecycle: nil,
3478+
expectedLifecycle: nil,
3479+
},
3480+
// feature gate is turned off and StopSignal is in use - StopSignal is not dropped
3481+
{
3482+
featuregateEnabled: false,
3483+
oldLifecycle: &api.Lifecycle{StopSignal: ptr.To(api.SIGTERM)},
3484+
newLifecycle: &api.Lifecycle{StopSignal: ptr.To(api.SIGTERM)},
3485+
expectedLifecycle: &api.Lifecycle{StopSignal: ptr.To(api.SIGTERM)},
3486+
},
3487+
// feature gate is turned off and StopSignal is not in use - Entire lifecycle is dropped
3488+
{
3489+
featuregateEnabled: false,
3490+
oldLifecycle: &api.Lifecycle{StopSignal: nil},
3491+
newLifecycle: &api.Lifecycle{StopSignal: ptr.To(api.SIGTERM)},
3492+
expectedLifecycle: nil,
3493+
},
3494+
// feature gate is turned on and StopSignal is in use - StopSignal is not dropped
3495+
{
3496+
featuregateEnabled: true,
3497+
oldLifecycle: &api.Lifecycle{StopSignal: nil},
3498+
newLifecycle: &api.Lifecycle{StopSignal: ptr.To(api.SIGTERM)},
3499+
expectedLifecycle: &api.Lifecycle{StopSignal: ptr.To(api.SIGTERM)},
3500+
},
3501+
// feature gate is turned off and PreStop is in use - StopSignal alone is dropped
3502+
{
3503+
featuregateEnabled: false,
3504+
oldLifecycle: &api.Lifecycle{StopSignal: nil, PreStop: &api.LifecycleHandler{
3505+
Exec: &api.ExecAction{Command: []string{"foo"}},
3506+
}},
3507+
newLifecycle: &api.Lifecycle{StopSignal: ptr.To(api.SIGTERM), PreStop: &api.LifecycleHandler{
3508+
Exec: &api.ExecAction{Command: []string{"foo"}},
3509+
}},
3510+
expectedLifecycle: &api.Lifecycle{StopSignal: nil, PreStop: &api.LifecycleHandler{
3511+
Exec: &api.ExecAction{Command: []string{"foo"}},
3512+
}},
3513+
},
3514+
// feature gate is turned on and PreStop is in use - StopSignal is not dropped
3515+
{
3516+
featuregateEnabled: true,
3517+
oldLifecycle: &api.Lifecycle{StopSignal: nil, PreStop: &api.LifecycleHandler{
3518+
Exec: &api.ExecAction{Command: []string{"foo"}},
3519+
}},
3520+
newLifecycle: &api.Lifecycle{StopSignal: ptr.To(api.SIGTERM), PreStop: &api.LifecycleHandler{
3521+
Exec: &api.ExecAction{Command: []string{"foo"}},
3522+
}},
3523+
expectedLifecycle: &api.Lifecycle{StopSignal: ptr.To(api.SIGTERM), PreStop: &api.LifecycleHandler{
3524+
Exec: &api.ExecAction{Command: []string{"foo"}},
3525+
}},
3526+
},
3527+
// feature gate is turned off and PreStop and StopSignal are in use - nothing is dropped
3528+
{
3529+
featuregateEnabled: true,
3530+
oldLifecycle: &api.Lifecycle{StopSignal: ptr.To(api.SIGTERM), PreStop: &api.LifecycleHandler{
3531+
Exec: &api.ExecAction{Command: []string{"foo"}},
3532+
}},
3533+
newLifecycle: &api.Lifecycle{StopSignal: ptr.To(api.SIGTERM), PreStop: &api.LifecycleHandler{
3534+
Exec: &api.ExecAction{Command: []string{"foo"}},
3535+
}},
3536+
expectedLifecycle: &api.Lifecycle{StopSignal: ptr.To(api.SIGTERM), PreStop: &api.LifecycleHandler{
3537+
Exec: &api.ExecAction{Command: []string{"foo"}},
3538+
}},
3539+
},
3540+
}
3541+
3542+
for i, tc := range testCases {
3543+
t.Run(fmt.Sprintf("test_%d", i), func(t *testing.T) {
3544+
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ContainerStopSignals, tc.featuregateEnabled)
3545+
// Containers
3546+
{
3547+
oldPod := makePod(api.Linux, []api.Container{makeContainer(tc.oldLifecycle.DeepCopy())}, nil, nil)
3548+
newPod := makePod(api.Linux, []api.Container{makeContainer(tc.newLifecycle.DeepCopy())}, nil, nil)
3549+
expectedPod := makePod(api.Linux, []api.Container{makeContainer(tc.expectedLifecycle.DeepCopy())}, nil, nil)
3550+
dropDisabledFields(newPod, nil, oldPod, nil)
3551+
3552+
if diff := cmp.Diff(expectedPod, newPod); diff != "" {
3553+
t.Fatalf("Unexpected modification to new pod; diff (-got +want)\n%s", diff)
3554+
}
3555+
}
3556+
// InitContainers
3557+
{
3558+
oldPod := makePod(api.Linux, nil, []api.Container{makeContainer(tc.oldLifecycle.DeepCopy())}, nil)
3559+
newPod := makePod(api.Linux, nil, []api.Container{makeContainer(tc.newLifecycle.DeepCopy())}, nil)
3560+
expectPod := makePod(api.Linux, nil, []api.Container{makeContainer(tc.expectedLifecycle.DeepCopy())}, nil)
3561+
dropDisabledFields(newPod, nil, oldPod, nil)
3562+
if diff := cmp.Diff(expectPod, newPod); diff != "" {
3563+
t.Fatalf("Unexpected modification to new pod; diff (-got +want)\n%s", diff)
3564+
}
3565+
}
3566+
// EphemeralContainers
3567+
{
3568+
oldPod := makePod(api.Linux, nil, nil, []api.EphemeralContainer{makeEphemeralContainer(tc.oldLifecycle.DeepCopy())})
3569+
newPod := makePod(api.Linux, nil, nil, []api.EphemeralContainer{makeEphemeralContainer(tc.newLifecycle.DeepCopy())})
3570+
expectPod := makePod(api.Linux, nil, nil, []api.EphemeralContainer{makeEphemeralContainer(tc.expectedLifecycle.DeepCopy())})
3571+
dropDisabledFields(newPod, nil, oldPod, nil)
3572+
if diff := cmp.Diff(expectPod, newPod); diff != "" {
3573+
t.Fatalf("Unexpected modification to new pod; diff (-got +want)\n%s", diff)
3574+
}
3575+
}
3576+
3577+
})
3578+
}
3579+
}
3580+
34393581
func TestDropSupplementalGroupsPolicy(t *testing.T) {
34403582
supplementalGroupsPolicyMerge := api.SupplementalGroupsPolicyMerge
34413583
podWithSupplementalGroupsPolicy := func() *api.Pod {

0 commit comments

Comments
 (0)