1
2
3
4
5
6
7
8
9
10
11
12
13
14 package chaos
15
16 import (
17 "context"
18 "fmt"
19 "net/http"
20 "strconv"
21 "time"
22
23 "github.com/onsi/ginkgo"
24 v1 "k8s.io/api/core/v1"
25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26 "k8s.io/apimachinery/pkg/labels"
27 "k8s.io/apimachinery/pkg/runtime"
28 "k8s.io/client-go/kubernetes"
29 clientgoscheme "k8s.io/client-go/kubernetes/scheme"
30 restClient "k8s.io/client-go/rest"
31 "k8s.io/kubernetes/test/e2e/framework"
32 "sigs.k8s.io/controller-runtime/pkg/client"
33
34 "github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
35 "github.com/chaos-mesh/chaos-mesh/pkg/portforward"
36 e2econfig "github.com/chaos-mesh/chaos-mesh/test/e2e/config"
37 "github.com/chaos-mesh/chaos-mesh/test/e2e/e2econst"
38 "github.com/chaos-mesh/chaos-mesh/test/e2e/util"
39 "github.com/chaos-mesh/chaos-mesh/test/pkg/fixture"
40
41
42 dnschaostestcases "github.com/chaos-mesh/chaos-mesh/test/e2e/chaos/dnschaos"
43 iochaostestcases "github.com/chaos-mesh/chaos-mesh/test/e2e/chaos/iochaos"
44 networkchaostestcases "github.com/chaos-mesh/chaos-mesh/test/e2e/chaos/networkchaos"
45 podchaostestcases "github.com/chaos-mesh/chaos-mesh/test/e2e/chaos/podchaos"
46 sidecartestcases "github.com/chaos-mesh/chaos-mesh/test/e2e/chaos/sidecar"
47 timechaostestcases "github.com/chaos-mesh/chaos-mesh/test/e2e/chaos/timechaos"
48 )
49
50 var _ = ginkgo.Describe("[Basic]", func() {
51 f := framework.NewDefaultFramework("chaos-mesh")
52 var ns string
53 var fwCancel context.CancelFunc
54 var fw portforward.PortForward
55 var kubeCli kubernetes.Interface
56 var config *restClient.Config
57 var cli client.Client
58 c := http.Client{
59 Timeout: 10 * time.Second,
60 }
61
62 ginkgo.BeforeEach(func() {
63 ns = f.Namespace.Name
64 ctx, cancel := context.WithCancel(context.Background())
65 clientRawConfig, err := e2econfig.LoadClientRawConfig()
66 framework.ExpectNoError(err, "failed to load raw config")
67 fw, err = portforward.NewPortForwarder(ctx, e2econfig.NewSimpleRESTClientGetter(clientRawConfig), true)
68 framework.ExpectNoError(err, "failed to create port forwarder")
69 fwCancel = cancel
70 kubeCli = f.ClientSet
71 config, err = framework.LoadConfig()
72 framework.ExpectNoError(err, "config error")
73 scheme := runtime.NewScheme()
74 _ = clientgoscheme.AddToScheme(scheme)
75 _ = v1alpha1.AddToScheme(scheme)
76 cli, err = client.New(config, client.Options{Scheme: scheme})
77 framework.ExpectNoError(err, "create client error")
78 })
79
80 ginkgo.AfterEach(func() {
81 if fwCancel != nil {
82 fwCancel()
83 }
84 })
85
86 ginkgo.Context("[PodChaos]", func() {
87 ginkgo.Context("[PodFailure]", func() {
88 ginkgo.It("[Schedule]", func() {
89 podchaostestcases.TestcasePodFailureOnceThenDelete(ns, kubeCli, cli)
90 })
91 ginkgo.It("[Pause]", func() {
92 podchaostestcases.TestcasePodFailurePauseThenUnPause(ns, kubeCli, cli)
93 })
94 })
95 ginkgo.Context("[PodKill]", func() {
96 ginkgo.It("[Schedule]", func() {
97 podchaostestcases.TestcasePodKillOnceThenDelete(ns, kubeCli, cli)
98 })
99 ginkgo.It("[Pause]", func() {
100 podchaostestcases.TestcasePodKillPauseThenUnPause(ns, kubeCli, cli)
101 })
102 })
103 ginkgo.Context("[ContainerKill]", func() {
104 ginkgo.It("[Schedule]", func() {
105 podchaostestcases.TestcaseContainerKillOnceThenDelete(ns, kubeCli, cli)
106 })
107 ginkgo.It("[Pause]", func() {
108 podchaostestcases.TestcaseContainerKillPauseThenUnPause(ns, kubeCli, cli)
109 })
110 })
111 })
112
113
114 ginkgo.Context("[TimeChaos]", func() {
115
116 var err error
117 var port uint16
118 var pfCancel context.CancelFunc
119
120 ginkgo.JustBeforeEach(func() {
121 svc := fixture.NewE2EService("timer", ns)
122 _, err = kubeCli.CoreV1().Services(ns).Create(svc)
123 framework.ExpectNoError(err, "create service error")
124 nd := fixture.NewTimerDeployment("timer", ns)
125 _, err = kubeCli.AppsV1().Deployments(ns).Create(nd)
126 framework.ExpectNoError(err, "create timer deployment error")
127 err = util.WaitDeploymentReady("timer", ns, kubeCli)
128 framework.ExpectNoError(err, "wait timer deployment ready error")
129 _, port, pfCancel, err = portforward.ForwardOnePort(fw, ns, "svc/timer", 8080)
130 framework.ExpectNoError(err, "create helper port-forward failed")
131 })
132
133 ginkgo.JustAfterEach(func() {
134 if pfCancel != nil {
135 pfCancel()
136 }
137 })
138
139
140 ginkgo.Context("[TimeSkew]", func() {
141
142 ginkgo.It("[Schedule]", func() {
143 timechaostestcases.TestcaseTimeSkewOnceThenRecover(ns, cli, c, port)
144 })
145
146 ginkgo.It("[Pause]", func() {
147 timechaostestcases.TestcaseTimeSkewPauseThenUnpause(ns, cli, c, port)
148 })
149
150 ginkgo.It("[StartAtWaiting]", func() {
151 timechaostestcases.TestcaseTimeSkewStartAtWaitingThenIntoRunning(ns, cli, c, port)
152 })
153 })
154 })
155
156
157 ginkgo.Context("[IOChaos]", func() {
158
159 var (
160 err error
161 port uint16
162 pfCancel context.CancelFunc
163 )
164
165 ginkgo.JustBeforeEach(func() {
166 svc := fixture.NewE2EService("io", ns)
167 _, err = kubeCli.CoreV1().Services(ns).Create(svc)
168 framework.ExpectNoError(err, "create service error")
169 nd := fixture.NewIOTestDeployment("io-test", ns)
170 _, err = kubeCli.AppsV1().Deployments(ns).Create(nd)
171 framework.ExpectNoError(err, "create io-test deployment error")
172 err = util.WaitDeploymentReady("io-test", ns, kubeCli)
173 framework.ExpectNoError(err, "wait io-test deployment ready error")
174 _, port, pfCancel, err = portforward.ForwardOnePort(fw, ns, "svc/io", 8080)
175 framework.ExpectNoError(err, "create helper io port port-forward failed")
176 })
177
178 ginkgo.JustAfterEach(func() {
179 if pfCancel != nil {
180 pfCancel()
181 }
182 })
183
184
185 ginkgo.Context("[IODelay]", func() {
186
187 ginkgo.It("[Schedule]", func() {
188 iochaostestcases.TestcaseIODelayDurationForATimeThenRecover(ns, cli, c, port)
189 })
190
191 ginkgo.It("[Pause]", func() {
192 iochaostestcases.TestcaseIODelayDurationForATimePauseAndUnPause(ns, cli, c, port)
193 })
194 ginkgo.It("[SpecifyContainer]", func() {
195 iochaostestcases.TestcaseIODelayWithSpecifiedContainer(ns, cli, c, port)
196 })
197 ginkgo.It("[WrongSpec]", func() {
198 iochaostestcases.TestcaseIODelayWithWrongSpec(ns, cli, c, port)
199 })
200 })
201
202
203 ginkgo.Context("[IOErrno]", func() {
204
205 ginkgo.It("[Schedule]", func() {
206 iochaostestcases.TestcaseIOErrorDurationForATimeThenRecover(ns, cli, c, port)
207 })
208 ginkgo.It("[Pause]", func() {
209 iochaostestcases.TestcaseIOErrorDurationForATimePauseAndUnPause(ns, cli, c, port)
210 })
211 ginkgo.It("[SpecifyContainer]", func() {
212 iochaostestcases.TestcaseIOErrorWithSpecifiedContainer(ns, cli, c, port)
213 })
214 })
215
216
217 ginkgo.Context("[IOMistake]", func() {
218
219 ginkgo.It("[Schedule]", func() {
220 iochaostestcases.TestcaseIOMistakeDurationForATimeThenRecover(ns, cli, c, port)
221 })
222 ginkgo.It("[Pause]", func() {
223 iochaostestcases.TestcaseIOMistakeDurationForATimePauseAndUnPause(ns, cli, c, port)
224 })
225 ginkgo.It("[SpecifyContainer]", func() {
226 iochaostestcases.TestcaseIOMistakeWithSpecifiedContainer(ns, cli, c, port)
227 })
228 })
229 })
230
231 ginkgo.Context("[Sidecar Config]", func() {
232 var (
233 cmName string
234 cmNamespace string
235 )
236
237
238 ginkgo.JustAfterEach(func() {
239 kubeCli.CoreV1().ConfigMaps(cmNamespace).Delete(cmName, &metav1.DeleteOptions{})
240 })
241
242 ginkgo.Context("[Template Config]", func() {
243
244 ginkgo.It("[InValid ConfigMap key]", func() {
245 cmName = "incorrect-key-name"
246 cmNamespace = e2econst.ChaosMeshNamespace
247 sidecartestcases.TestcaseInvalidConfigMapKey(ns, cmNamespace, cmName, kubeCli, cli)
248 })
249
250 ginkgo.It("[InValid Configuration]", func() {
251 cmName = "incorrect-configuration"
252 cmNamespace = e2econst.ChaosMeshNamespace
253 sidecartestcases.TestcaseInvalidConfiguration(ns, cmNamespace, cmName, kubeCli, cli)
254 })
255 })
256
257 ginkgo.Context("[Injection Config]", func() {
258 ginkgo.It("[No Template]", func() {
259 cmName = "no-template-name"
260 cmNamespace = e2econst.ChaosMeshNamespace
261 sidecartestcases.TestcaseNoTemplate(ns, cmNamespace, cmName, kubeCli, cli)
262 })
263
264 ginkgo.It("[No Template Args]", func() {
265 cmName = "no-template-args"
266 cmNamespace = e2econst.ChaosMeshNamespace
267 sidecartestcases.TestcaseNoTemplateArgs(ns, cmNamespace, cmName, kubeCli, cli)
268 })
269 })
270 })
271
272 ginkgo.Context("[NetworkChaos]", func() {
273 var err error
274
275 var networkPeers []*v1.Pod
276 var ports []uint16
277 var pfCancels []context.CancelFunc
278
279 ginkgo.JustBeforeEach(func() {
280 ports = []uint16{}
281 networkPeers = []*v1.Pod{}
282 for index := 0; index < 4; index++ {
283 name := fmt.Sprintf("network-peer-%d", index)
284
285 svc := fixture.NewE2EService(name, ns)
286 _, err = kubeCli.CoreV1().Services(ns).Create(svc)
287 framework.ExpectNoError(err, "create service error")
288 nd := fixture.NewNetworkTestDeployment(name, ns, map[string]string{"partition": strconv.Itoa(index % 2)})
289 _, err = kubeCli.AppsV1().Deployments(ns).Create(nd)
290 framework.ExpectNoError(err, "create network-peer deployment error")
291 err = util.WaitDeploymentReady(name, ns, kubeCli)
292 framework.ExpectNoError(err, "wait network-peer deployment ready error")
293
294 pod, err := getPod(kubeCli, ns, name)
295 framework.ExpectNoError(err, "select network-peer pod error")
296 networkPeers = append(networkPeers, pod)
297
298 _, port, pfCancel, err := portforward.ForwardOnePort(fw, ns, "svc/"+svc.Name, 8080)
299 ports = append(ports, port)
300 pfCancels = append(pfCancels, pfCancel)
301 framework.ExpectNoError(err, "create helper io port port-forward failed")
302 }
303 })
304
305 ginkgo.Context("[ForbidHostNetwork]", func() {
306 ginkgo.It("[Schedule]", func() {
307 networkchaostestcases.TestcaseForbidHostNetwork(ns, kubeCli, cli)
308 })
309 })
310
311 ginkgo.Context("[NetworkPartition]", func() {
312 ginkgo.It("[Schedule]", func() {
313 networkchaostestcases.TestcaseNetworkPartition(ns, cli, networkPeers, ports, c)
314 })
315 })
316
317 ginkgo.Context("[Netem]", func() {
318 ginkgo.It("[Schedule]", func() {
319 networkchaostestcases.TestcaseNetworkDelay(ns, cli, networkPeers, ports, c)
320 })
321 ginkgo.It("[PeersCrossoverWithDirectionBoth]", func() {
322 networkchaostestcases.TestcasePeersCrossover(ns, cli, networkPeers, ports, c)
323 })
324 })
325
326 ginkgo.JustAfterEach(func() {
327 for _, cancel := range pfCancels {
328 cancel()
329 }
330 })
331 })
332
333 ginkgo.Context("[DNSChaos]", func() {
334 var err error
335 var port uint16
336
337 ginkgo.JustBeforeEach(func() {
338 name := "network-peer"
339
340 svc := fixture.NewE2EService(name, ns)
341 _, err = kubeCli.CoreV1().Services(ns).Create(svc)
342 framework.ExpectNoError(err, "create service error")
343 nd := fixture.NewNetworkTestDeployment(name, ns, map[string]string{"partition": "0"})
344 _, err = kubeCli.AppsV1().Deployments(ns).Create(nd)
345 framework.ExpectNoError(err, "create network-peer deployment error")
346 err = util.WaitDeploymentReady(name, ns, kubeCli)
347 framework.ExpectNoError(err, "wait network-peer deployment ready error")
348
349 _, err = getPod(kubeCli, ns, name)
350 framework.ExpectNoError(err, "select network-peer pod error")
351
352 _, port, _, err = portforward.ForwardOnePort(fw, ns, "svc/"+svc.Name, 8080)
353 framework.ExpectNoError(err, "create helper io port port-forward failed")
354 })
355 ginkgo.It("[RANDOM]", func() {
356 dnschaostestcases.TestcaseDNSRandom(ns, cli, port, c)
357 })
358
359 ginkgo.It("[ERROR]", func() {
360 dnschaostestcases.TestcaseDNSError(ns, cli, port, c)
361 })
362 })
363 })
364
365 func getPod(kubeCli kubernetes.Interface, ns string, appLabel string) (*v1.Pod, error) {
366 listOption := metav1.ListOptions{
367 LabelSelector: labels.SelectorFromSet(map[string]string{
368 "app": appLabel,
369 }).String(),
370 }
371
372 pods, err := kubeCli.CoreV1().Pods(ns).List(listOption)
373 if err != nil {
374 return nil, err
375 }
376
377 if len(pods.Items) > 1 {
378 return nil, fmt.Errorf("select more than one pod")
379 }
380
381 if len(pods.Items) == 0 {
382 return nil, fmt.Errorf("cannot select any pod")
383 }
384
385 return &pods.Items[0], nil
386 }
387