Skip to content

Commit 3c8a2c2

Browse files
committed
Migrate OCP-38271 from openshift-tests-private
Add test to verify init containers do not restart when removed from node. - Add pod-initContainer.yaml template - Add helper functions in node_utils.go - Add OCP-38271 test in node_e2e/node.go Author: minmli@redhat.com (original) Migrated-by: bgudi@redhat.com Move OCP-38271 test to separate Describe block Refactor OCP-38271 to use standard origin patterns instead of compat_otp
1 parent c77ff4a commit 3c8a2c2

1 file changed

Lines changed: 156 additions & 2 deletions

File tree

test/extended/node/node_e2e/node.go

Lines changed: 156 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
package node
22

33
import (
4+
"context"
5+
"fmt"
6+
"regexp"
47
"strings"
58
"time"
69

710
g "github.com/onsi/ginkgo/v2"
811
o "github.com/onsi/gomega"
9-
nodeutils "github.com/openshift/origin/test/extended/node"
10-
exutil "github.com/openshift/origin/test/extended/util"
12+
corev1 "k8s.io/api/core/v1"
13+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1114
"k8s.io/apimachinery/pkg/util/wait"
1215
e2e "k8s.io/kubernetes/test/e2e/framework"
16+
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
17+
18+
nodeutils "github.com/openshift/origin/test/extended/node"
19+
exutil "github.com/openshift/origin/test/extended/util"
1320
)
1421

1522
var _ = g.Describe("[sig-node] [Jira:Node/Kubelet] Kubelet, CRI-O, CPU manager", func() {
@@ -104,3 +111,150 @@ var _ = g.Describe("[sig-node] [Jira:Node/Kubelet] Kubelet, CRI-O, CPU manager",
104111
o.Expect(output).To(o.ContainSubstring("spec.cgroupMode: Unsupported value: \"v1\": supported values: \"v2\", \"\""))
105112
})
106113
})
114+
115+
var _ = g.Describe("[sig-node] [Jira:Node/Kubelet] NODE initContainer policy,volume,readines,quota", func() {
116+
defer g.GinkgoRecover()
117+
118+
var (
119+
oc = exutil.NewCLI("node-initcontainer")
120+
)
121+
122+
// Skip all tests on MicroShift clusters as MachineConfig resources are not available
123+
g.BeforeEach(func() {
124+
isMicroShift, err := exutil.IsMicroShiftCluster(oc.AdminKubeClient())
125+
o.Expect(err).NotTo(o.HaveOccurred())
126+
if isMicroShift {
127+
g.Skip("Skipping test on MicroShift cluster - MachineConfig resources are not available")
128+
}
129+
})
130+
131+
//author: bgudi@redhat.com
132+
g.It("[OTP] Init containers should not restart when the exited init container is removed from node [OCP-38271]", func() {
133+
g.By("Test for case OCP-38271")
134+
oc.SetupProject()
135+
136+
podName := "initcon-pod"
137+
namespace := oc.Namespace()
138+
ctx := context.Background()
139+
140+
g.By("Create a pod with init container")
141+
pod := &corev1.Pod{
142+
ObjectMeta: metav1.ObjectMeta{
143+
Name: podName,
144+
Namespace: namespace,
145+
},
146+
Spec: corev1.PodSpec{
147+
InitContainers: []corev1.Container{
148+
{
149+
Name: "inittest",
150+
Image: "quay.io/openshifttest/busybox@sha256:c5439d7db88ab5423999530349d327b04279ad3161d7596d2126dfb5b02bfd1f",
151+
Command: []string{"bin/sh", "-ec", "echo running >> /mnt/data/test"},
152+
VolumeMounts: []corev1.VolumeMount{
153+
{
154+
Name: "data",
155+
MountPath: "/mnt/data",
156+
},
157+
},
158+
},
159+
},
160+
Containers: []corev1.Container{
161+
{
162+
Name: "hello-test",
163+
Image: "quay.io/openshifttest/busybox@sha256:c5439d7db88ab5423999530349d327b04279ad3161d7596d2126dfb5b02bfd1f",
164+
Command: []string{"bin/sh", "-c", "sleep 3600"},
165+
VolumeMounts: []corev1.VolumeMount{
166+
{
167+
Name: "data",
168+
MountPath: "/mnt/data",
169+
},
170+
},
171+
},
172+
},
173+
Volumes: []corev1.Volume{
174+
{
175+
Name: "data",
176+
VolumeSource: corev1.VolumeSource{
177+
EmptyDir: &corev1.EmptyDirVolumeSource{},
178+
},
179+
},
180+
},
181+
RestartPolicy: corev1.RestartPolicyNever,
182+
},
183+
}
184+
185+
_, err := oc.KubeClient().CoreV1().Pods(namespace).Create(ctx, pod, metav1.CreateOptions{})
186+
o.Expect(err).NotTo(o.HaveOccurred())
187+
defer func() {
188+
oc.KubeClient().CoreV1().Pods(namespace).Delete(ctx, podName, metav1.DeleteOptions{})
189+
}()
190+
191+
g.By("Check pod status")
192+
err = e2epod.WaitForPodRunningInNamespace(ctx, oc.KubeClient(), pod)
193+
o.Expect(err).NotTo(o.HaveOccurred(), "pod is not running")
194+
195+
g.By("Check init container exit normally")
196+
err = wait.Poll(5*time.Second, 1*time.Minute, func() (bool, error) {
197+
pod, err := oc.KubeClient().CoreV1().Pods(namespace).Get(ctx, podName, metav1.GetOptions{})
198+
if err != nil {
199+
return false, err
200+
}
201+
for _, status := range pod.Status.InitContainerStatuses {
202+
if status.Name == "inittest" {
203+
if status.State.Terminated != nil && status.State.Terminated.ExitCode == 0 {
204+
e2e.Logf("Init container exited with code 0")
205+
return true, nil
206+
}
207+
}
208+
}
209+
return false, nil
210+
})
211+
o.Expect(err).NotTo(o.HaveOccurred(), "container not exit normally")
212+
213+
g.By("Get node where pod is running")
214+
pod, err = oc.KubeClient().CoreV1().Pods(namespace).Get(ctx, podName, metav1.GetOptions{})
215+
o.Expect(err).NotTo(o.HaveOccurred())
216+
nodeName := pod.Spec.NodeName
217+
o.Expect(nodeName).NotTo(o.BeEmpty(), "pod node name is empty")
218+
219+
g.By("Get init container ID from pod status")
220+
var containerID string
221+
for _, status := range pod.Status.InitContainerStatuses {
222+
if status.Name == "inittest" {
223+
containerID = status.ContainerID
224+
break
225+
}
226+
}
227+
o.Expect(containerID).NotTo(o.BeEmpty(), "init container ID is empty")
228+
229+
// Extract the actual container ID (remove prefix like "cri-o://")
230+
containerIDPattern := regexp.MustCompile(`^[^/]+://(.+)$`)
231+
matches := containerIDPattern.FindStringSubmatch(containerID)
232+
o.Expect(matches).To(o.HaveLen(2), "failed to parse container ID")
233+
actualContainerID := matches[1]
234+
235+
g.By("Delete init container from node")
236+
deleteCmd := fmt.Sprintf("crictl rm %s", actualContainerID)
237+
output, err := nodeutils.ExecOnNodeWithChroot(oc, nodeName, "/bin/bash", "-c", deleteCmd)
238+
o.Expect(err).NotTo(o.HaveOccurred(), "fail to delete container")
239+
e2e.Logf("Container deletion output: %s", output)
240+
241+
g.By("Check init container not restart again")
242+
err = wait.Poll(5*time.Second, 1*time.Minute, func() (bool, error) {
243+
pod, err := oc.KubeClient().CoreV1().Pods(namespace).Get(ctx, podName, metav1.GetOptions{})
244+
if err != nil {
245+
return false, err
246+
}
247+
for _, status := range pod.Status.InitContainerStatuses {
248+
if status.Name == "inittest" {
249+
if status.RestartCount > 0 {
250+
e2e.Logf("Init container restarted, restart count: %d", status.RestartCount)
251+
return false, fmt.Errorf("init container restarted")
252+
}
253+
}
254+
}
255+
e2e.Logf("Init container has not restarted")
256+
return true, nil
257+
})
258+
o.Expect(err).NotTo(o.HaveOccurred(), "init container restart")
259+
})
260+
})

0 commit comments

Comments
 (0)