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