Add support for kube TerminationGracePeriodSeconds

Add support to kube play to support the TerminationGracePeriodSeconds
fiels by sending the value of that to podman's stopTimeout.
Add support to kube generate to generate TerminationGracePeriodSeconds
if stopTimeout is set for a container (will ignore podman's default).

Signed-off-by: Urvashi Mohnani <umohnani@redhat.com>
This commit is contained in:
Urvashi Mohnani
2023-09-10 16:37:07 -04:00
parent 51d01dd38e
commit d9a85466a0
6 changed files with 88 additions and 7 deletions

View File

@ -33,7 +33,7 @@ Note: **N/A** means that the option cannot be supported in a single-node Podman
| topologySpreadConstraints\.labelSelector | N/A |
| topologySpreadConstraints\.minDomains | N/A |
| restartPolicy | ✅ |
| terminationGracePeriod | no |
| terminationGracePeriodSeconds | |
| activeDeadlineSeconds | no |
| readinessGates\.conditionType | no |
| hostname | ✅ |

View File

@ -435,7 +435,10 @@ func (p *Pod) podWithContainers(ctx context.Context, containers []*Container, po
podInitCtrs := []v1.Container{}
podAnnotations := make(map[string]string)
dnsInfo := v1.PodDNSConfig{}
var hostname string
var (
hostname string
stopTimeout *uint
)
// Let's sort the containers in order of created time
// This will ensure that the init containers are defined in the correct order in the kube yaml
@ -463,6 +466,12 @@ func (p *Pod) podWithContainers(ctx context.Context, containers []*Container, po
}
}
// Pick the first container that has a stop-timeout set and use that value
// Ignore podman's default
if ctr.config.StopTimeout != util.DefaultContainerConfig().Engine.StopTimeout && stopTimeout == nil {
stopTimeout = &ctr.config.StopTimeout
}
ctr, volumes, _, annotations, err := containerToV1Container(ctx, ctr, getService)
if err != nil {
return nil, err
@ -536,10 +545,11 @@ func (p *Pod) podWithContainers(ctx context.Context, containers []*Container, po
&dnsInfo,
hostNetwork,
hostUsers,
hostname), nil
hostname,
stopTimeout), nil
}
func newPodObject(podName string, annotations map[string]string, initCtrs, containers []v1.Container, volumes []v1.Volume, dnsOptions *v1.PodDNSConfig, hostNetwork, hostUsers bool, hostname string) *v1.Pod {
func newPodObject(podName string, annotations map[string]string, initCtrs, containers []v1.Container, volumes []v1.Volume, dnsOptions *v1.PodDNSConfig, hostNetwork, hostUsers bool, hostname string, stopTimeout *uint) *v1.Pod {
tm := v12.TypeMeta{
Kind: "Pod",
APIVersion: "v1",
@ -571,6 +581,10 @@ func newPodObject(podName string, annotations map[string]string, initCtrs, conta
if dnsOptions != nil && (len(dnsOptions.Nameservers)+len(dnsOptions.Searches)+len(dnsOptions.Options) > 0) {
ps.DNSConfig = dnsOptions
}
if stopTimeout != nil {
terminationGracePeriod := int64(*stopTimeout)
ps.TerminationGracePeriodSeconds = &terminationGracePeriod
}
p := v1.Pod{
TypeMeta: tm,
ObjectMeta: om,
@ -590,8 +604,11 @@ func simplePodWithV1Containers(ctx context.Context, ctrs []*Container, getServic
podDNS := v1.PodDNSConfig{}
kubeAnnotations := make(map[string]string)
ctrNames := make([]string, 0, len(ctrs))
var hostname string
var restartPolicy *string
var (
hostname string
restartPolicy *string
stopTimeout *uint
)
for _, ctr := range ctrs {
ctrNames = append(ctrNames, removeUnderscores(ctr.Name()))
for k, v := range ctr.config.Spec.Annotations {
@ -616,6 +633,12 @@ func simplePodWithV1Containers(ctx context.Context, ctrs []*Container, getServic
}
}
// Pick the first container that has a stop-timeout set and use that value
// Ignore podman's default
if ctr.config.StopTimeout != util.DefaultContainerConfig().Engine.StopTimeout && stopTimeout == nil {
stopTimeout = &ctr.config.StopTimeout
}
// Use the restart policy of the first non-init container
if !isInit && restartPolicy == nil {
restartPolicy = &ctr.config.RestartPolicy
@ -707,7 +730,8 @@ func simplePodWithV1Containers(ctx context.Context, ctrs []*Container, getServic
&podDNS,
hostNetwork,
hostUsers,
hostname)
hostname,
stopTimeout)
// Set the pod's restart policy
policy := ""

View File

@ -855,6 +855,10 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
Volumes: volumes,
}
if podYAML.Spec.TerminationGracePeriodSeconds != nil {
specgenOpts.TerminationGracePeriodSeconds = podYAML.Spec.TerminationGracePeriodSeconds
}
specGen, err := kube.ToSpecGen(ctx, &specgenOpts)
if err != nil {
return nil, nil, err

View File

@ -168,6 +168,8 @@ type CtrSpecGenOptions struct {
InitContainerType string
// PodSecurityContext is the security context specified for the pod
PodSecurityContext *v1.PodSecurityContext
// TerminationGracePeriodSeconds is the grace period given to a container to stop before being forcefully killed
TerminationGracePeriodSeconds *int64
}
func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGenerator, error) {
@ -584,6 +586,12 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
s.Labels[systemdDefine.EnvVariable] = unit
}
// Set the stopTimeout if terminationGracePeriodSeconds is set in the kube yaml
if opts.TerminationGracePeriodSeconds != nil {
timeout := uint(*opts.TerminationGracePeriodSeconds)
s.StopTimeout = &timeout
}
return s, nil
}

View File

@ -52,6 +52,7 @@ var _ = Describe("Podman kube generate", func() {
Expect(pod.Spec.Containers[0].SecurityContext).To(BeNil())
Expect(pod.Spec.Containers[0].Env).To(BeNil())
Expect(pod).To(HaveField("Name", "top-pod"))
Expect(pod.Spec.TerminationGracePeriodSeconds).To(BeNil())
numContainers := 0
for range pod.Spec.Containers {
@ -1880,4 +1881,25 @@ EXPOSE 2004-2005/tcp`, ALPINE)
Expect(err).ToNot(HaveOccurred())
Expect(pod.Annotations).To(BeEmpty())
})
It("podman generate kube on pod with --stop-timeout set for ctr", func() {
podName := "test-pod"
podSession := podmanTest.Podman([]string{"pod", "create", podName})
podSession.WaitWithDefaultTimeout()
Expect(podSession).Should(Exit(0))
session := podmanTest.Podman([]string{"create", "--pod", podName, "--stop-timeout", "20", ALPINE, "top"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
kube := podmanTest.Podman([]string{"generate", "kube", podName})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
// TerminationGracePeriodSeconds should be set to 20
pod := new(v1.Pod)
err := yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).ToNot(HaveOccurred())
Expect(int(*pod.Spec.TerminationGracePeriodSeconds)).To(Equal(20))
})
})

View File

@ -5991,4 +5991,27 @@ EXPOSE 2004-2005/tcp`, ALPINE)
Expect(inspect).Should(Exit(0))
Expect(inspect.OutputToString()).To(ContainSubstring(`FOO=bar`))
})
It("podman kube play with TerminationGracePeriodSeconds set", func() {
ctrName := "ctr"
ctrNameInPod := "ctr-pod-ctr"
outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml")
create := podmanTest.Podman([]string{"create", "--restart", "never", "--stop-timeout", "20", "--name", ctrName, ALPINE})
create.WaitWithDefaultTimeout()
Expect(create).Should(Exit(0))
generate := podmanTest.Podman([]string{"kube", "generate", "-f", outputFile, ctrName})
generate.WaitWithDefaultTimeout()
Expect(generate).Should(Exit(0))
play := podmanTest.Podman([]string{"kube", "play", outputFile})
play.WaitWithDefaultTimeout()
Expect(play).Should(Exit(0))
inspect := podmanTest.Podman([]string{"inspect", ctrNameInPod, "-f", "{{ .Config.StopTimeout }}"})
inspect.WaitWithDefaultTimeout()
Expect(inspect).Should(Exit(0))
Expect(inspect.OutputToString()).To(Equal("20"))
})
})