1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package podchaos
17
18 import (
19 "context"
20 "time"
21
22 . "github.com/onsi/ginkgo/v2"
23 corev1 "k8s.io/api/core/v1"
24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25 "k8s.io/apimachinery/pkg/labels"
26 "k8s.io/apimachinery/pkg/types"
27 "k8s.io/apimachinery/pkg/util/wait"
28 "k8s.io/client-go/kubernetes"
29 "k8s.io/kubernetes/test/e2e/framework"
30 "k8s.io/utils/pointer"
31 "sigs.k8s.io/controller-runtime/pkg/client"
32
33 "github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
34 "github.com/chaos-mesh/chaos-mesh/e2e-test/e2e/util"
35 "github.com/chaos-mesh/chaos-mesh/e2e-test/pkg/fixture"
36 )
37
38 func TestcaseContainerKillOnceThenDelete(ns string, kubeCli kubernetes.Interface, cli client.Client) {
39 ctx, cancel := context.WithCancel(context.Background())
40 defer cancel()
41
42 nd := fixture.NewCommonNginxDeployment("nginx", ns, 1)
43 _, err := kubeCli.AppsV1().Deployments(ns).Create(context.TODO(), nd, metav1.CreateOptions{})
44 framework.ExpectNoError(err, "create nginx deployment error")
45 err = util.WaitDeploymentReady("nginx", ns, kubeCli)
46 framework.ExpectNoError(err, "wait nginx deployment ready error")
47
48 containerKillChaos := &v1alpha1.PodChaos{
49 ObjectMeta: metav1.ObjectMeta{
50 Name: "nginx-container-kill",
51 Namespace: ns,
52 },
53 Spec: v1alpha1.PodChaosSpec{
54 Action: v1alpha1.ContainerKillAction,
55 ContainerSelector: v1alpha1.ContainerSelector{
56 PodSelector: v1alpha1.PodSelector{
57 Selector: v1alpha1.PodSelectorSpec{
58 GenericSelectorSpec: v1alpha1.GenericSelectorSpec{
59 Namespaces: []string{
60 ns,
61 },
62 LabelSelectors: map[string]string{
63 "app": "nginx",
64 },
65 },
66 },
67 Mode: v1alpha1.OneMode,
68 },
69 ContainerNames: []string{"nginx"},
70 },
71 },
72 }
73 err = cli.Create(ctx, containerKillChaos)
74 framework.ExpectNoError(err, "create container kill chaos error")
75
76 err = wait.PollImmediate(5*time.Second, 5*time.Minute, func() (done bool, err error) {
77 listOption := metav1.ListOptions{
78 LabelSelector: labels.SelectorFromSet(map[string]string{
79 "app": "nginx",
80 }).String(),
81 }
82 pods, err := kubeCli.CoreV1().Pods(ns).List(context.TODO(), listOption)
83 if err != nil {
84 return false, nil
85 }
86 if len(pods.Items) != 1 {
87 return false, nil
88 }
89 pod := pods.Items[0]
90 for _, cs := range pod.Status.ContainerStatuses {
91 if cs.Name == "nginx" && cs.LastTerminationState.Terminated != nil {
92 return true, nil
93 }
94 }
95 return false, nil
96 })
97 framework.ExpectNoError(err, "container kill apply failed")
98
99 err = cli.Delete(ctx, containerKillChaos)
100 framework.ExpectNoError(err, "failed to delete container kill chaos")
101
102 By("success to perform container kill")
103 err = wait.PollImmediate(5*time.Second, 5*time.Minute, func() (done bool, err error) {
104 listOption := metav1.ListOptions{
105 LabelSelector: labels.SelectorFromSet(map[string]string{
106 "app": "nginx",
107 }).String(),
108 }
109 pods, err := kubeCli.CoreV1().Pods(ns).List(context.TODO(), listOption)
110 if err != nil {
111 return false, nil
112 }
113 if len(pods.Items) != 1 {
114 return false, nil
115 }
116 pod := pods.Items[0]
117 for _, cs := range pod.Status.ContainerStatuses {
118 if cs.Name == "nginx" && cs.Ready && cs.State.Running != nil {
119 return true, nil
120 }
121 }
122 return false, nil
123 })
124 framework.ExpectNoError(err, "container kill recover failed")
125
126 }
127
128 func TestcaseContainerKillPauseThenUnPause(ns string, kubeCli kubernetes.Interface, cli client.Client) {
129 ctx, cancel := context.WithCancel(context.Background())
130 defer cancel()
131 nd := fixture.NewCommonNginxDeployment("nginx", ns, 1)
132 _, err := kubeCli.AppsV1().Deployments(ns).Create(context.TODO(), nd, metav1.CreateOptions{})
133 framework.ExpectNoError(err, "create nginx deployment error")
134 err = util.WaitDeploymentReady("nginx", ns, kubeCli)
135 framework.ExpectNoError(err, "wait nginx deployment ready error")
136
137 var pods *corev1.PodList
138 var newPods *corev1.PodList
139 listOption := metav1.ListOptions{
140 LabelSelector: labels.SelectorFromSet(map[string]string{
141 "app": "nginx",
142 }).String(),
143 }
144 pods, err = kubeCli.CoreV1().Pods(ns).List(context.TODO(), listOption)
145 framework.ExpectNoError(err, "get nginx pods error")
146
147
148 containerID := pods.Items[0].Status.ContainerStatuses[0].ContainerID
149
150 containerKillChaos := &v1alpha1.PodChaos{
151 ObjectMeta: metav1.ObjectMeta{
152 Name: "nginx-container-kill",
153 Namespace: ns,
154 },
155 Spec: v1alpha1.PodChaosSpec{
156 Action: v1alpha1.ContainerKillAction,
157 Duration: pointer.String("9m"),
158 ContainerSelector: v1alpha1.ContainerSelector{
159 PodSelector: v1alpha1.PodSelector{
160 Selector: v1alpha1.PodSelectorSpec{
161 GenericSelectorSpec: v1alpha1.GenericSelectorSpec{
162 Namespaces: []string{
163 ns,
164 },
165 LabelSelectors: map[string]string{
166 "app": "nginx",
167 },
168 },
169 },
170 Mode: v1alpha1.OneMode,
171 },
172 ContainerNames: []string{"nginx"},
173 },
174 },
175 }
176 err = cli.Create(ctx, containerKillChaos)
177 framework.ExpectNoError(err, "create container kill chaos error")
178
179 chaosKey := types.NamespacedName{
180 Namespace: ns,
181 Name: "nginx-container-kill",
182 }
183
184
185 err = wait.Poll(5*time.Second, 5*time.Minute, func() (done bool, err error) {
186 newPods, err = kubeCli.CoreV1().Pods(ns).List(context.TODO(), listOption)
187 framework.ExpectNoError(err, "get nginx pods error")
188 return containerID != newPods.Items[0].Status.ContainerStatuses[0].ContainerID, nil
189 })
190 framework.ExpectNoError(err, "wait container kill failed")
191
192
193 err = util.PauseChaos(ctx, cli, containerKillChaos)
194 framework.ExpectNoError(err, "pause chaos error")
195
196 err = wait.Poll(1*time.Second, 10*time.Second, func() (done bool, err error) {
197 chaos := &v1alpha1.PodChaos{}
198 err = cli.Get(ctx, chaosKey, chaos)
199 framework.ExpectNoError(err, "get pod chaos error")
200 if chaos.Status.Experiment.DesiredPhase == v1alpha1.StoppedPhase {
201 return true, nil
202 }
203 return false, err
204 })
205 framework.ExpectError(err, "one-shot chaos shouldn't enter stopped phase")
206
207
208 pods, err = kubeCli.CoreV1().Pods(ns).List(context.TODO(), listOption)
209 framework.ExpectNoError(err, "get nginx pods error")
210 containerID = pods.Items[0].Status.ContainerStatuses[0].ContainerID
211 err = wait.Poll(5*time.Second, 1*time.Minute, func() (done bool, err error) {
212 newPods, err = kubeCli.CoreV1().Pods(ns).List(context.TODO(), listOption)
213 framework.ExpectNoError(err, "get nginx pods error")
214 return containerID != newPods.Items[0].Status.ContainerStatuses[0].ContainerID, nil
215 })
216 framework.ExpectError(err, "wait container not killed failed")
217 framework.ExpectEqual(err.Error(), wait.ErrWaitTimeout.Error())
218
219
220 err = util.UnPauseChaos(ctx, cli, containerKillChaos)
221 framework.ExpectNoError(err, "resume chaos error")
222
223 err = wait.Poll(5*time.Second, 5*time.Minute, func() (done bool, err error) {
224 chaos := &v1alpha1.PodChaos{}
225 err = cli.Get(ctx, chaosKey, chaos)
226 framework.ExpectNoError(err, "get pod chaos error")
227 if chaos.Status.Experiment.DesiredPhase == v1alpha1.RunningPhase {
228 return true, nil
229 }
230 return false, err
231 })
232 framework.ExpectNoError(err, "chaos should keep in running phase")
233
234
235 pods, err = kubeCli.CoreV1().Pods(ns).List(context.TODO(), listOption)
236 framework.ExpectNoError(err, "get nginx pods error")
237 containerID = pods.Items[0].Status.ContainerStatuses[0].ContainerID
238 err = wait.Poll(1*time.Second, 10*time.Second, func() (done bool, err error) {
239 newPods, err = kubeCli.CoreV1().Pods(ns).List(context.TODO(), listOption)
240 framework.ExpectNoError(err, "get nginx pods error")
241 return containerID != newPods.Items[0].Status.ContainerStatuses[0].ContainerID, nil
242 })
243 framework.ExpectError(err, "container shouldn't be killed")
244
245 }
246